題目描述:給定一棵任意二元樹(非完全二元樹),其節點除了 val、left、right 之外還有一個 next 指標,初始值皆為 nullptr。請將每個節點的 next 指向同一層的下一個右邊節點;若右邊沒有節點,next 設為 nullptr。要求使用 O(1) 額外空間(不得使用佇列或陣列)。
解題思路:
本題是 LeetCode 116 的進階版——樹不再是完全二元樹,因此不能直接依賴 node->left->next = node->right 這類規律。核心技巧是:利用當前層已建立好的 next 指標,來建構下一層的 next 鏈。
cur 指向當前層的最左節點;每次處理完當前層,就推進到下一層的最左節點。dummy,並用 tail 指標追蹤下一層的「最後一個已串好的節點」。遍歷當前層時,每當遇到子節點,就把它接到 tail->next,並推進 tail。cur = cur->next 水平移動,這是 O(1) 空間實作的關鍵——不需要額外佇列,完全依賴已建立的 next 鏈。cur = dummy->next(即下一層的實際起點),進入下一輪迭代。此做法時間複雜度 O(n),空間複雜度 O(1)。
時間複雜度:O(n) — 每個節點恰好被走訪一次(外層迴圈逐層推進,內層迴圈處理當前層所有節點),n 為樹的節點總數。
空間複雜度:O(1) — 僅使用固定個數的指標變數(cur、dummy、tail),不使用佇列、堆疊或陣列;虛擬頭節點在堆疊上分配,不計入額外空間。
1. If root is null, return null.
2. Set cur = root (leftmost node of current level).
3. While cur is not null:
a. Create a dummy node; set tail = dummy.
b. While cur is not null:
- If cur.left exists: tail.next = cur.left; tail = tail.next.
- If cur.right exists: tail.next = cur.right; tail = tail.next.
- Advance cur = cur.next (move right on the current level).
c. Advance cur = dummy.next (move down to next level's first node).
4. Return root.方法一:BFS 佇列(Level-Order Traversal)
使用 queue<Node*> 進行標準 BFS,每次處理一整層時,將同層節點依序串接 next 指標。時間複雜度 O(n),空間複雜度 O(n)(佇列最大存放一層所有節點,最壞情況為葉層的 n/2 個節點)。實作直觀,但不符合題目 O(1) 空間的要求。
方法二:DFS 遞迴(前序走訪)
以前序走訪(根→左→右)遞迴處理,利用已建立的 next 鏈橫向搜尋同層下一個可串接的子節點。空間複雜度 O(h)(h 為樹高,遞迴堆疊),最壞情況 O(n)。邏輯較複雜,且無法達到嚴格 O(1) 額外空間,但對完全二元樹(LeetCode 116)而言遞迴解較易理解。
dummy 虛擬節點是在每一層的迴圈開始時建立的。如果改成在迴圈外只建立一次並反覆重置,有哪些細節需要注意(例如如何清除 dummy.next)?next 指標?