↓快轉到主要內容
  1. LeetCode/

LeetCode 1008: Construct Binary Search Tree from Preorder Traversal

·1 分鐘· ·
LeetCode Medium Tree Bst Binary-Tree Recursion
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2025-07-16

  • 提交紀錄:Accepted(一次通過)

解題思路
#

Preorder 的第一個值是根。因為是 BST,後面比根小的值全部屬於左子樹,比根大的值全部屬於右子樹,兩邊各自遞迴就好。

我的解法:把陣列切兩半再遞迴
#

class Solution:
    def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:
        if not preorder:
            return None

        root = TreeNode(preorder[0], None, None)
        left = []
        right = []
        for node in preorder[1:]:
            if node < root.val:
                left.append(node)
            else:
                right.append(node)

        if left:
            root.left = self.bstFromPreorder(left)
        if right:
            root.right = self.bstFromPreorder(right)
        return root

正確,n <= 100 也很快。但每一層都要掃過剩下的陣列並建新的 list,遇到已排序的輸入(樹退化成一條鏈)會變成 O(n^2)。

更好的解法:帶上界遞迴,O(n)
#

依照 preorder 的順序一個一個取值,同時告訴遞迴「這棵子樹的值不能超過多少」:

  • 左子樹的上界是根的值。
  • 右子樹沿用父節點傳下來的上界。
  • 下一個值超過上界時,代表它不屬於這棵子樹,回傳 None 讓上一層處理。
class Solution:
    def bstFromPreorder(self, preorder: List[int]) -> Optional[TreeNode]:
        i = 0

        def build(bound: float) -> Optional[TreeNode]:
            nonlocal i
            if i == len(preorder) or preorder[i] > bound:
                return None
            root = TreeNode(preorder[i])
            i += 1
            root.left = build(root.val)
            root.right = build(bound)
            return root

        return build(float("inf"))

每個值只被取一次,所以是 O(n)。

複雜度
#

解法時間空間
切陣列遞迴最壞 O(n^2)O(n^2)(每層新建 list)
帶上界遞迴O(n)O(h) 遞迴深度

要特別避免的錯誤
#

  • i 在巢狀函式裡被重新賦值,要用 nonlocal。
  • 左子樹的上界寫成 bound 而不是 root.val,會把右子樹的值也收進左邊。

面試口說整理
#

Preorder 第一個值是根,後面比它小的屬於左子樹。直接切陣列遞迴是 O(n^2),所以我改成依序取值,並帶著上界遞迴:左子樹上界是根的值,右子樹沿用原本的上界;下一個值超過上界就回傳 None。每個值只處理一次,時間 O(n)。

相關文章

LeetCode 958: Check Completeness of a Binary Tree
·1 分鐘
LeetCode Medium Tree Binary-Tree Bfs
LeetCode 958 解題筆記:完整性是整體性質,用 BFS 檢查第一個空位之後還有沒有節點
LeetCode 103: Binary Tree Zigzag Level Order Traversal
·1 分鐘
LeetCode Medium Tree Breadth-First-Search Binary-Tree
LeetCode 103 解題筆記:一般的層序遍歷,奇數層的結果反轉就是之字形
LeetCode 107: Binary Tree Level Order Traversal II
·1 分鐘
LeetCode Medium Tree Breadth-First-Search Binary-Tree
LeetCode 107 解題筆記:一般的層序遍歷,最後把結果反轉,就是由下往上
LeetCode 113: Path Sum II
·1 分鐘
LeetCode Medium Backtracking Tree Depth-First-Search Binary-Tree
LeetCode 113 解題筆記:回溯記錄目前的路徑,到葉子時總和等於目標就存一份複本;值可能是負的,不能提早剪枝
LeetCode 129: Sum Root to Leaf Numbers
·1 分鐘
LeetCode Medium Tree Depth-First-Search Binary-Tree
LeetCode 129 解題筆記:往下走時目前的數字乘 10 加上節點的值,到葉子時加進總和
LeetCode 222: Count Complete Tree Nodes
·1 分鐘
LeetCode Medium Binary-Search Bit-Manipulation Tree Binary-Tree
LeetCode 222 解題筆記:完全二元樹,左右兩邊的最左高度相同代表那一邊是滿的,直接用 2^h - 1;O(log² n)