題目描述:給定一棵「完全二元樹」(complete binary tree)的根節點,計算其節點總數。完全二元樹的定義是:除最後一層外,每一層都是完全填滿的;最後一層的節點全部靠左對齊。要求時間複雜度優於 O(n)。
解題思路:關鍵在於利用完全二元樹的特性避免逐一訪問每個節點。對於任一子樹,分別計算其最左路徑高度 lh(一直走 left)和最右路徑高度 rh(一直走 right):
lh == rh:這棵子樹是一棵完美二元樹(perfect binary tree),節點數恰好為 2^lh - 1,直接公式計算,無需繼續遞迴。lh != rh:這棵子樹不是完美二元樹,遞迴計算左子樹和右子樹的節點數,再加上根節點本身(+1)。每次遞迴至少有一側子樹會被公式直接解決,因此遞迴深度為 O(log n),每層計算高度需 O(log n) 時間,整體為 O(log² n)。
時間複雜度:O(log² n) — 遞迴深度為 O(log n)(每次至少有一側子樹被公式解決),每層計算最左和最右路徑高度各需 O(log n),兩者相乘得 O(log² n)。
空間複雜度:O(log n) — 遞迴呼叫堆疊的深度,等於樹高,完全二元樹的高度為 O(log n)。
1. If root is null: return 0 2. Compute lh = height following only left children from root 3. Compute rh = height following only right children from root 4. If lh == rh: a. This is a perfect binary tree b. Return (2^lh) - 1 5. Else: a. Return 1 + countNodes(root.left) + countNodes(root.right)
方法一:普通 DFS / BFS 暴力計數 直接對整棵樹做 DFS 或 BFS,每訪問一個節點就計數加一。實作最簡單,但時間複雜度為 O(n),沒有利用完全二元樹的性質,不符合題目「優於 O(n)」的要求。
方法二:二元搜尋 + 位元編碼 完全二元樹高度為 h,最後一層有 1 到 2^(h-1) 個節點。用二元搜尋在 [1, 2^(h-1)] 範圍內找最後一個存在的節點編號:用從根開始的位元路徑(第 i 位決定走 left 或 right)來判斷某編號的節點是否存在。時間複雜度同為 O(log² n),但常數較大、實作較複雜。
方法三:迭代版高度比較 將遞迴方法改寫為迭代(使用明確迴圈和指標),避免遞迴呼叫堆疊,在函數呼叫開銷較大的環境下可略微提升實際效能,時間複雜度不變。
1 << lh 在 32 位元整數下會溢位,應如何修改程式碼以處理這種情況?