题目:
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).