您的位置:首页 > Web前端 > Node.js

[Leetcode] Populating Next Right Pointers in Each Node II

2014-10-22 12:15 405 查看
题目:

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous solution still work?

Note:
You may only use constant extra space.

For example,

Given the following binary tree,

1
/  \
2    3
/ \    \
4   5    7


After calling your function, the tree should look like:

1 -> NULL
/  \
2 -> 3 -> NULL
/ \    \
4-> 5 -> 7 -> NULL


思路一:和Populating Next Right Pointers in Each Node I类似,DFS解决。区别在于,需要定义一个函数找到当前root子节点的下一个子节点。方法是从当前root顺着next指针一直找,直到找到一个有子节点的node,返回那个node的子节点。另一个改动是,由于这个函数需要一直顺着next找过去,如果递归的时候先处理左子树,会导致root层的next指针没有处理完全,进而导致无法找到root子节点的下一个子节点。因此,需要先递归右子树,再递归左子树。为什么这样做就可以呢?原因在于,先递归右子树的情况下,root层的next指针依然无法处理完全,但是未处理过的next指针总是在当前root的左边,并不影响寻找下一个子节点。相反,如果先处理左子树,未处理过的next指针总是在当前root的右边,会导致无法找到下一个子节点。第二个问题是,那为什么在Populating
Next Right Pointers in Each Node I中可以先处理左子树呢?原因在于对于一个满的树,寻找下一个子节点仅需要当前root的next已经连接即可,并不关心更远处的next是否处理过。但对于一个不满的树,就有可能需要走到很远的地方去寻找下一个子节点。

class Solution {
public:
    TreeLinkNode* next_child_peer(TreeLinkNode* root) {
        if (root == nullptr) return nullptr;
        TreeLinkNode* runner = root->next;
        while (runner != nullptr) {
            if (runner->left != nullptr) return runner->left;
            if (runner->right != nullptr) return runner->right;
            runner = runner->next;
        }
        return nullptr;
    }
    
    void connect(TreeLinkNode *root) {
        if (root == nullptr) return;
        if (root->left != nullptr) {
            if (root->right != nullptr) {
                root->left->next = root->right;
            } else {
                root->left->next = next_child_peer(root);
            }
        }
        if (root->right != nullptr) {
            root->right->next = next_child_peer(root);
        }
        connect(root->right);
        connect(root->left);
    }
};


总结:复杂度为O(2^n). 

思路二:类似的,DFS所用空间为O(h),如果想达到常数空间,需要使用BFS. 方法和 I 类似,只不过下一层的第一个元素不一定是当前层第一个元素的左子节点,在遍历当前层的时候寻找第一个出现的子节点即可。

class Solution {
public:
    TreeLinkNode* next_child_peer(TreeLinkNode* root) {
        if (root == nullptr) return nullptr;
        TreeLinkNode* runner = root->next;
        while (runner != nullptr) {
            if (runner->left != nullptr) return runner->left;
            if (runner->right != nullptr) return runner->right;
            runner = runner->next;
        }
        return nullptr;
    }
    
    void connect(TreeLinkNode *root) {
        if (root == nullptr) return;
        TreeLinkNode* level_head = root;
        while (level_head != nullptr) {
            TreeLinkNode* level_runner = level_head;
            level_head = nullptr;
            while (level_runner != nullptr) {
                if (level_runner->left != nullptr) {
                    if (level_head == nullptr) {   //find the head of the next level
                        level_head = level_runner->left;
                    }
                    if (level_runner->right != nullptr) {
                        level_runner->left->next = level_runner->right;
                    } else {
                        level_runner->left->next = next_child_peer(level_runner);
                    }
                }
                if (level_runner->right != nullptr) {
                    if (level_head == nullptr) {   //find the head of the next level
                        level_head = level_runner->right;
                    }
                    level_runner->right->next = next_child_peer(level_runner);
                }
                level_runner = level_runner->next;
            }
        }
    }
};


总结:复杂度为O(2^n). 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: