Leetcode 117:填充同一層的兄弟節點 II(超詳細的解法!!!)
給定一個二叉樹
struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}
填充它的每個 next 指標,讓這個指標指向其下一個右側節點。如果找不到下一個右側節點,則將 next 指標設定為 NULL
。
初始狀態下,所有 next 指標都被設定為 NULL
。
說明:
- 你只能使用額外常數空間。
- 使用遞迴解題也符合要求,本題中遞迴程式佔用的棧空間不算做額外的空間複雜度。
示例:
給定二叉樹,
1 / \ 2 3 / \ \ 4 5 7
呼叫你的函式後,該二叉樹變為:
1 -> NULL
/ \
2 -> 3 -> NULL
/ \ \
4-> 5 -> 7 -> NULL
解題思路
和之前問題類似Leetcode 116:填充同一層的兄弟節點(超詳細的解法!!!)
我們可以直接採用之前的第一種解法。
class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
if not root:
return
q = [root, None]
while q:
node = q.pop(0)
if node:
node.next = q[0]
if node.left:
q.append(node.left)
if node.right:
q.append( node.right)
else:
if q:
q.append(None)
同樣可以減少空間複雜度,我們可以建立兩個指標dummy
和node
,並且二者初始時引用同一節點。
如果root.left
不為空的話,我們就將node.next=root.left
,並且node=node.next
。
如果root.right
不為空的話,我們就將node.next=root.right
,並且node=node.next
。然後我們看root.next
是不是空,如果不是的話,繼續root.next
的連結,否則進入下一層root=dummy.next
。(和之前的第二種解法類似)
class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
while root:
node = dummy = TreeLinkNode(0)
while root:
if root.left:
node.next = node = root.left
if root.right:
node.next = node = root.right
root = root.next
root = dummy.next
同樣這個問題我們也可以通過遞迴來解決。關鍵問題在於找到同一層上非空的節點,我們可以單獨建立一個函式findNext
實現相關操作。這個函式也非常容易實現,如果root
為空,我們直接返回。如果root.left
不為空,我們返回root.left
。如果root.right
不為空,我們返回root.right
。
class Solution:
# @param root, a tree link node
# @return nothing
def connect(self, root):
if not root:
return
if root.left:
if root.right:
root.left.next = root.right
else:
root.left.next = self.findNext(root.next)
if root.right:
root.right.next = self.findNext(root.next)
self.connect(root.right)
self.connect(root.left)
def findNext(self, cur):
if not cur:
return None
if cur.left:
return cur.left
if cur.right:
return cur.right
return self.findNext(cur.next)
這裡要注意一個細節,我們在主函式中遞迴遍歷的順序和之前問題相反,先root.right
再root.left
。我們舉個例子
如果我們先left
再right
的話,我們的9
是無法指向10
的。因為我們的5.right
是空,所以我們會通過findNext(5.next)
去尋找非空節點,但是由於6
的左右都為空,所以會繼續findNext(6.next)
,但是此時我們6
和7
還未連結,所以結果就是8 → 9 → null
。
但是如果我們先right
再left
的話,此時我們的6
和7
可以保證連結,那麼此時findNext(6)
找不到的話,我們會繼續findNext(6.next)
也就是findNext(7)
。
reference:
我將該問題的其他語言版本新增到了我的GitHub Leetcode
如有問題,希望大家指出!!!