題目描述:給定一個升序排列的整數陣列 nums,請將其轉換為一棵高度平衡的二元搜尋樹(BST)。高度平衡指的是:樹中每個節點的左右子樹高度差不超過 1。
解題思路:由於輸入陣列已是有序陣列,若要讓 BST 保持高度平衡,最自然的做法就是每次選取陣列的中間元素作為當前子樹的根節點。如此一來,左半部分的元素組成左子樹,右半部分的元素組成右子樹,兩側元素個數差最多為 1,因此樹的高度必然平衡。
以遞迴方式實作:定義函式 build(left, right),代表使用索引範圍 [left, right] 的元素建構子樹。每次計算中間索引 mid = (left + right) / 2,以 nums[mid] 建立根節點,再對左半區間 [left, mid-1] 遞迴建立左子樹,對右半區間 [mid+1, right] 遞迴建立右子樹。當 left > right 時回傳 nullptr 作為終止條件。整體思路類似二分搜尋的分治概念,每次將問題規模減半。
時間複雜度:O(n) — 陣列中每個元素恰好被訪問一次,用於建立對應的樹節點,因此總時間與元素個數 n 成線性關係。
空間複雜度:O(log n) — 遞迴呼叫棧的深度等於樹的高度,由於樹是高度平衡的,高度為 O(log n)。若計入輸出樹本身佔用的節點空間,則輸出空間為 O(n),但通常遞迴棧空間才是分析重點。
1. Define helper function build(nums, left, right): a. If left > right, return null (base case) b. Compute mid = left + (right - left) / 2 c. Create a new tree node with value nums[mid] d. Recursively build left subtree from nums[left..mid-1] e. Recursively build right subtree from nums[mid+1..right] f. Return the new node 2. Call build(nums, 0, nums.size() - 1) and return the result.
方法一:選取右中間元素作為根
每次取 mid = (left + right + 1) / 2(向上取整),同樣能建出高度平衡的 BST,只是當元素個數為偶數時,根節點偏向右側。時間複雜度同為 O(n)。LeetCode 接受多種合法答案,此方法同樣正確。
方法二:中序遍歷 + 計數模擬(迭代) 以迭代方式模擬中序遍歷,維護一個全域計數器,依序為陣列中的每個值填入 BST 節點。先用遞迴計算子樹結構(節點個數),再逐步取值。雖然概念清晰,但實作較為繁瑣,空間複雜度仍為 O(log n)(呼叫棧),時間複雜度 O(n),實務上不如直接取中間索引的方法簡潔。