1. 程式人生 > >Leetcode 117:填充同一層的兄弟節點 II(超詳細的解法!!!)

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)

同樣可以減少空間複雜度,我們可以建立兩個指標dummynode,並且二者初始時引用同一節點。

如果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.rightroot.left。我們舉個例子

如果我們先leftright的話,我們的9是無法指向10的。因為我們的5.right是空,所以我們會通過findNext(5.next)去尋找非空節點,但是由於6的左右都為空,所以會繼續findNext(6.next),但是此時我們67還未連結,所以結果就是8 → 9 → null

但是如果我們先rightleft的話,此時我們的67可以保證連結,那麼此時findNext(6)找不到的話,我們會繼續findNext(6.next)也就是findNext(7)

reference:

https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/discuss/37879/Simple-C%2B%2B-Recursion-With-Comments

我將該問題的其他語言版本新增到了我的GitHub Leetcode

如有問題,希望大家指出!!!