項目 widget-area-1 尚未註冊或是沒有一個 view.php 檔案.
項目 widget-area-1 尚未註冊或是沒有一個 view.php 檔案.
項目 search-input 尚未註冊或是沒有一個 view.php 檔案.

【Leetcode】python – [144] Binary Tree Preorder Traversal 個人解法筆記 (內含範例程式碼) 內含 處理 Tree 樹問題的重點

題目出處

144. Binary Tree Preorder Traversal

難度

easy

題目分類

Stack, Tree, Depth-First Search, Binary Tree

個人範例程式碼 – recursive 版

Tree 基本中的基本,我們一定至少需要學會兩種 parse tree 的方式,

  • 一種是 iterative (直接的取)
  • 另一種是 recursive (遞迴的取)

基本上這兩種都務必熟悉,未來解題時萬一一種解不出來,就可以嘗試用另外一種方法。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # pre = m l r
        if not root:
            return []
        else:
            ans = [] # in-place change
            self.dfs(root, ans)
            return ans

    def dfs(self, node, ans):
        if not node:
            return
        else:
            ans.append(node.val) # mid
            self.dfs(node.left, ans) # l
            self.dfs(node.right, ans) # r

        return ans

算法說明

recursive 的 parse tree 基本上可以結合 dfs 的概念,
而我門需要另外寫一個 function dfs(),因為我們會需要把答案帶著走,原題目的函數沒辦法直接遞迴。

corner case 特殊情況處理

當樹為空 [] 或 為只有 root [1] 時,需要注意。

Boundary conditions/ Edge conditions 邊際情況處理

處理沒有節點的情況, if not root 直接回傳。

另外一種漂亮的解法:直接只處理 「if root:」,我們才做事情。

個人範例程式碼 – iterative 版

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # pre = m l r
        ans = []
        node_stack = [root]
        while node_stack:
            cur_node = node_stack.pop()
            if cur_node:
                ans.append(cur_node.val)
                node_stack.append(cur_node.right)
                node_stack.append(cur_node.left)

        return ans

算法說明

直覺上的解法我們需要配合 Stack,遞迴的做法我們需要配合 DFS。
Stack 為 pop() 或 pop(-1) 就可以直接實現。

注意:由於「後處理要先放」,因此順序會是「先右後左」

你可能會想問這麼注意順序為什麼不用 Queue?
因為「先進先出」的結構我們沒辦法保存應該要後處理的東西。

例如 第一層的 左右,加入第二層後,
第一層的右一定會先出後,才會做第二層,因此沒辦法。

corner case 特殊情況處理

當樹為空 [] 或 為只有 root [1] 時,需要注意。

Boundary conditions/ Edge conditions 邊際情況處理

結束條件為 Stack 為空,我們運用 Stack 可以幫我們保存的概念。

結論 – 處理樹的重點

直接的解法我們需要配合 Stack,遞迴的做法我們需要配合 DFS