LeetCode #117 Populating Next Right Pointers in Each Node II - 刷題之旅
1 題目描述
給定一個二元樹,然後每個節點有一個 next 指針,將它指向它右邊的節點。如果沒有右邊的節點,則設為 None。
題目有特殊要求,不能使用額外的空間,也就是說不能使用 Queue 來解這題。
2 解法
我們先走簡單路線,你會發現基本上就是把同一層的節點串起來,然後再串下一層的節點。因此我們可以使用BFS的方式來解這題。講到BFS的演算法,可以參考這篇LeetCode 課前預習 - 掌握 BFS 與 DFS 指南。
2.1 Queue
我們可以知道在Iterative的方式下,先不考慮題目限制,我們可以使用Queue來解這題。
BFS的演算法
1 | def bfs_traversal(root): |
從上面得到一個概念,那就是如果我們把 next_level
也就是當前的 nodes
串起來,不就達到題目的要求了嗎?我們希望在執行 for loop 每個 node
的時候,可以把 nodes
之間串起來。可以先建立一個 dummyhead
,然後串 node
,這樣進入 for loop 的時候,就可以 dummyhead.next
串起來,傳完後再重新把 dummyhead
斷開就好。
大概是這種感覺:
把同level的nodes串起來
1 | dummy = Node(-1) |
基本上我們就完成了,以下是完整的程式碼:
1 | def connect(self, root: Node) -> Node: |
2.2 Space O(1)
但是這樣還不夠,因為題目有要求 O(1)的空間限制,因此我們不能使用 Queue 來解這題。我參考了這篇Leetcode wang的文章,我覺得挺清楚的。通常講到 O(1) 就要聯想到 pointer,那我們需要兩個pointer:
- 一個pointer紀錄上一層的level的node,我們稱作
pre
; - 另一個pointer紀錄當前層level的node,我們稱作
cur
pre
跟cur
都要往右移動,也就是cur
負責串當前層的節點,pre
負責移動上一層的node,以方便cur
繼續連下一個樹同層的節點。大概是這種感覺:
處理
pre
的子節點時,cur
要負責把小孩子都串起來
當
cur
的小孩子串完後,pre
要往右移動,cur
才可以繼續串
從以上規律可以發現:
dummy
負責串每層的第一個pre
會一直往右走直到觸底,就換下層的第一個,可以指向dummy.next
cur
負責把當前的層串起來
完整程式碼如下
1 | def connect(self, root: Node) -> Node: |
3 總結
這題花了大概30分鐘想出來,這是我第一次寫BFS的題目,因此還是有借住一點idea,搭配BFS的演算法,免強想出一個O(n)空間複雜度的解法。這題的重點在於,如何把同一層的節點串起來,然後再串下一層的節點。這樣的題目,我覺得還是要多練習,才能更加熟練。