[ Leetcode ] Binary Tree - Modify And Construct
Contents
Base Questions
Modify Binary Tree
- Recursive
- preorder traversal
- traversal 輸入參數與返回值恰好與題目相同,直接使用題目函式進行遞迴
1 2 3 4 5 6 7
def invertTree(root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: return root root.left, root.right = root.right, root.left # 中 invertTree(root.left) # 左 invertTree(root.right) # 右 return root
- Iterative
- preorder traversal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
def invertTree(root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: return root stack = [] stack.append(root) while stack: node = stack[-1] if node: stack.pop() if node.right: stack.append(node.right) # 右 if node.left: stack.append(node.left) # 左 stack.append(node) # 中 stack.append(None) #加入空節點 else: stack.pop() #彈出空節點 node = stack.pop() # 彈出目標節點 node.left, node.right = node.right, node.left # 執行單層所需操作 return root
- level traversal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from collections import deque def invertTree(root: Optional[TreeNode]) -> Optional[TreeNode]: if root is None: return root que = deque() que.append(root) while que: size = len(que) for _ in range(size): node = que.popleft() node.left, node.right = node.right, node.left # 中 if node.left: que.append(node.left) # 左 if node.right: que.append(node.right) # 右 return root
Construct Binary Tree
106. Construct Binary Tree from Inorder and Postorder Traversal
- concept : 用後序探訪的特性得知最後探訪的為根節點,搭配中序定位左右子樹,便可確立唯一二元樹
- Recursive
- 參數與返回值
- 參數:後序與中序的陣列
- 返回值:唯一二元樹的根節點
- 終止條件
- 後序陣列長度為0,探訪至葉節點,唯一二元樹建置完成
- 單層邏輯
- 從後序最後一個值作為當前根節點,建制新的子樹
- 找到根節點在中序的位置 index,作為切割點
- 切割中序陣列,切成中序的左右子樹陣列
- 切割後序陣列,切成後序的左右子樹陣列
- 遞回處理左右區間
- 參數與返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
def buildTree(inorder: List[int], postorder: List[int]) -> Optional[TreeNode]: def traversal(inorder, postorder) -> Optional[TreeNode]: if len(postorder) == 0: return None rootValue = postorder[-1] root = TreeNode(rootValue) if len(postorder) == 1: return root delimiterIndex = inorder.index(rootValue) leftInorder = inorder[:delimiterIndex] rightInorder = inorder[delimiterIndex + 1:] postorder.pop() leftPostorder = postorder[:len(leftInorder)] rightPostorder = postorder[len(leftInorder):] root.left = traversal(leftInorder, leftPostorder) root.right = traversal(rightInorder, rightPostorder) return root if not inorder or not postorder: return None return traversal(inorder, postorder)
- Recursive
- 參數與返回值
- 參數:當下節點所需元素的陣列
- 返回值:用輸入陣列構成的二元樹根節點
- 終止條件
- 輸入陣列長度為 1,即已探訪至葉節點
- 單層邏輯
- 找到輸入陣列最大值作為根節點
- 找到根節點在陣列的位置 index,作為切割點
- 以切割點建構左右子樹 (前提是要確保有值才建立子樹)
- 參數與返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
def constructMaximumBinaryTree(nums: List[int]) -> Optional[TreeNode]: if len(nums) == 1: return TreeNode(nums[0]) maxValue = max(nums) maxValueIndex = nums.index(maxValue) node = TreeNode(maxValue) if maxValueIndex > 0: # 確保有值才能建立子樹 node.left = self.constructMaximumBinaryTree(nums[:maxValueIndex]) if maxValueIndex < len(nums) - 1: # 確保有值才能建立子樹 node.right = self.constructMaximumBinaryTree(nums[maxValueIndex + 1:]) return node
- Recursive
- Recursive (以前序為例,最好理解)
- 參數與返回值
- 參數:兩樹根節點
- 返回值:合併後,樹的根節點
- 終止條件
- 兩樹合併後,只會存在一棵樹,所以若一其一為空,則返回另一棵不為空的樹
- 單層邏輯
- 因爲合併後的樹只有一顆,所以可用任一棵樹進行操作
- 先更新當前節點值,再遞回更新子樹
- 參數與返回值
1 2 3 4 5 6 7 8 9
def mergeTrees(root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: if root1 is None: return root2 if root2 is None: return root1 root1.val += root2.val # 中 root1.left = mergeTrees(root1.left, root2.left) # 左 root1.right = mergeTrees(root1.right, root2.right) # 右 return root1
- Iterative
- 使用 Queue 存放元素
- levelorder traversal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
from collections import deque def mergeTrees(root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]: if root1 is None: return root2 if root2 is None: return root1 que = deque([root1, root2]) while que: node1 = que.popleft() node2 = que.popleft() node1.val += node2.val if node1.left is not None and node2.left is not None: que.append(node1.left) que.append(node2.left) if node1.right is not None and node2.right is not None: que.append(node1.right) que.append(node2.right) if node1.left is None and node2.left is not None: node1.left = node2.left if node1.right is None and node2.right is not None: node1.right = node2.right return root1
- Recursive (以前序為例,最好理解)