前中後序遍歷二叉樹 6 道 ( 遞歸 + 非遞歸)
遞歸忽略
前序遍歷
準備一個 stack, 因爲是前序,頭結點要先打印,則放入頭節點後立馬彈出, 在彈出的時候查詢是否有孩子節點,按照先右後左的順序壓入棧中。
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
stack = [root]
res = []
while stack:
pop = stack.pop()
if pop.right:
stack.append(pop.right)
if pop.left:
stack.append(pop.left)
res.append(pop.val)
return res
中序遍歷
stack 備好, 有左孩子就一直放,放到不能再放就彈出, 因爲中序遍歷爲 左 -> 中 -> 右, 左邊彈出後下一個 彈出爲 中, 有右再放入
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
res,stack = [], []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left
pop = stack.pop()
cur = pop.right
res.append(pop.val)
return res
後序遍歷
依然準備stack,如果我們正向收集數組,先收集 中, 再收集左, 最後右, 整個翻過來就是後序的順序
class Solution:
def postorderTraversal(self, root: TreeNode) -> List[int]:
if not root :
return []
stack, res = [root],[]
while stack:
pop = stack.pop()
res.append(pop.val)
if pop.left:
stack.append(pop.left)
if pop.right:
stack.append(pop.right)
return res[::-1]
其他遍歷
層次遍歷
zig zag 遍歷
搜索二叉樹相關
左中右大小順序滿足: 小 中 大, 這樣的構造就是搜索二叉樹, 換言之,右邊的子樹都大於 左, 中
判斷是否爲搜索二叉樹
遞歸
嚴格按照定義出發, 左邊的小於中間,中間小於右邊
class Solution:
def isValidBST(self, root: TreeNode) -> bool:
# 如果 head.val 在兩個數之間,則爲 true,
def helper(head, smaller, bigger):
if not head:
return True
if smaller >= head.val or head.val >= bigger:
return False
# 左子樹, head.val 爲最大的數字
if not helper(head.left, smaller, head.val):
return False
# 右子樹, head.val 爲最小的數字
if not helper(head.right, head.val, bigger):
return False
return True
return helper(root, -sys.maxsize, sys.maxsize)
中序
省略了,直接收集到結果,看一下是不是升序就好
將有序數組轉化爲平衡搜索二叉樹
看起來有平衡貌似多了個條件,其實是幫助我們做題, 有序數組中位可以作爲搜索二叉樹的頭節點, 中位數之前爲左樹,中位數之後爲右樹,遞歸。
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
if not nums:
return None
def InOrderSort(arr)-> TreeNode:
if not arr:
return
mid = len(arr) // 2
node = TreeNode(arr[mid])
node.left = InOrderSort(arr[:mid])
node.right = InOrderSort(arr[mid + 1:])
return node
return InOrderSort(nums)
構造樹
前序與中序遍歷構造二叉樹
前序遍歷數組,第一個元素是整個樹的頭結點,在中序列遍歷中, 頭結點左邊右邊便是這個樹的左子樹與右子樹,遞歸構造
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
if len(preorder) != len(inorder):
return None
def build(preo, ino):
if not preo or not ino:
return
root_val = preo[0]
left_len = 0
for i in range(len(ino)):
if root_val == ino[i]:
# 從零開始,左邊的長度與根節點的index一致
left_len = i
break
root = TreeNode(root_val)
root.left = build(preo[1: left_len + 1], ino[:left_len])
root.right = build(preo[left_len + 1:], ino[left_len + 1:])
return root
return build(preorder, inorder)
後序與中序遍歷構造二叉樹
思路與上題相似, 後序遍歷中,根節點在數組的最後位置,其他與上題幾乎無差別,這裏使用下py api 來做
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
if not inorder:
return None
root = TreeNode(postorder[-1])
i = inorder.index(root.val)
root.left = self.buildTree(inorder[:i], postorder[:i])
root.right = self.buildTree(inorder[i+1:], postorder[i:-1])
return root