LeetCode 116, 117. Populating Next Right Pointers in Each Node I + II

116. Populating Next Right Pointers in Each Node

直接做的话用levelOrder做即可,但是要求空间复杂度O(1),所以不行。

Recursive

这里递归是preOrder,一定要先将root的左右儿子连接起来,后面递归才能继续连接。

这里每次dfs到root的时候是处理孩子,而不是将当前root和右边的node连接,是因为我们无法得到右边节点的信息(我们无法返回到当前root的parent)。先将左儿子和右儿子连接起来,然后连接右儿子和右边的节点(由于preOrder,root已经连接完毕,我们可以通过 root->next->left 找到右边的节点)。

class Solution {
public:
    void connect(TreeLinkNode *root) {
        if (root==NULL) return;
        if (root->left){ // if root has two sons
            root->left->next = root->right;
            if (root->next!=NULL){
                root->right->next = root->next->left;
            }
        }
        connect(root->left);
        connect(root->right);
    }
};

如果不算递归所用栈的空间的话O(1)。 

Non-recursive

思路和levelOrder一样,不同的是不借助queue。每次连接下一层的node,通过next遍历这一层的所有节点(这样下一层的节点就都连接好了)。root = root->left 到下一层继续。

class Solution {
public:
    void connect(TreeLinkNode *root) {
        TreeLinkNode *cur;
        while (root!=NULL){
            cur = root;
            while (cur!=NULL){
                if (cur->left!=NULL){
                    cur->left->next = cur->right;
                    if (cur->next){
                        cur->right->next = cur->next->left;
                    }
                }
                cur = cur->next;
            }
            root = root->left;
        }        
    }
};

 

117. Populating Next Right Pointers in Each Node II

相比上一题缺少了perfect binary tree的限制,但是思路还是一样的。

Recursive (116-like)

前一题我们只要连接root->left和root->right,以及root->right和root->next->left。但是对于本题来说,需要连接的node有很多情况。这里我们引入一个helper function findNext(),找到需要连接的右边的节点。这个function也是递归的。

但是需要特别注意的是,这里我们要根右左,即最后先connect(root->right),再connect(root->left)。这是因为findNext函数可能会递归root->next->next ... ,如果右边此时没有处理好的话,就会报错。

                   2
                  /  \
                 1-> 3
                / \  / \
               0->7->9 1
              /  / \  / \
            2-> 1->"0"8  8

如图所示,如果根左右,处理到“0”的时候,findNext(7) 会调用 findNext(9),导致错误发生。

class Solution {
public:
    void connect(Node* root) { //修改成void
        if (root==NULL) return;
        if (root->left){
            if (root->right) root->left->next = root->right;
            else root->left->next = findNext(root->next);
        }
        if (root->right){
            root->right->next = findNext(root->next);
        }
        connect(root->right);
        connect(root->left);
    }
    
    Node *findNext(Node *root){ // find the next node in the same level
        if (root==NULL) return NULL;
        if (root->left) return root->left;
        if (root->right) return root->right;
        return findNext(root->next);
    }
};

 

接下来的方法需要一个prev指针,用来连接。

Recursive (use prev)

https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/discuss/37953/C++-recursive-solution-easy-understanding 

Non-recursive

上一题的解法是连接root->left和root->right,以及root->right和root->next->left。由于next的节点不好找,我们可以用类似levelOrder遍历+prev来连接。进去下一个level我们可以用 root = dummy->next,因为dummy开始的这条链表就是连接好的下一层。

class Solution {
public: 
    void connect(Node* root) {
        while (root!=NULL){
            Node *dummy=new Node(0,NULL,NULL,NULL), *prev=dummy, *cur=root;
            while (cur){
                if (cur->left){
                    prev->next = cur->left;
                    prev = cur->left;
                }
                if (cur->right){
                    prev->next = cur->right;
                    prev = cur->right;
                }
                cur = cur->next;
            }
            root = dummy->next;
        }
    }
};

 

Reference

Mostly-recursive-solution-O(n)-time-(beats-99.32)-and-O(1)-space-(without-considering-stack)

C++-recursive-solution-easy-understanding 

not used

O(1)-space-O(n)-complexity-Iterative-Solution

Simple-40ms-c++-o(n)-o(1)-solution-with-only-one-while-loop

posted @ 2018-08-30 07:35  約束の空  阅读(98)  评论(0)    收藏  举报