116. Populating Next Right Pointers in Each Node
题目
You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
Note:
You may only use constant extra space.
Recursive approach is fine, implicit stack space does not count as extra space for this problem.
方法1: recursion
思路:
recursion要思考的问题是,在每一层需要解决什么问题?1. 自己的left和right要打通,2. 如果有next,right和next -> left要打通。通过这一点就已经完成了下一层所有节点的打通,而下层的事情交给孩子们去处理。这是一个必须遵循preorder的栗子,因为下面的实现依靠本层先打通下一层。
// 注意if判断条件之间的关系
// 题目要求:You may only use constant extra space.
class Solution {
public:
Node* connect(Node* root) {
if (!root) return root;
if (root -> left) {
root -> left -> next = root -> right;
}
if (root -> right && root -> next) {
root -> right -> next = root -> next -> left;
}
connect(root -> left);
connect(root -> right);
return root;
}
};
方法2: iterative
思路:
如何在O(1)的空间下实现遍历?本来iterative的方法是一定要借用stack的,才能回去找到后面的路,但是这里由于在遍历上一层的时候已经打通了本层的next,所以stack不必要,O(1)变为可能。每一层在已经打通的情况下要如何打通下一层?首先用一个cur遍历本层,在每一个节点cur必须负责1. 自己 cur -> left -> next = cur -> right 的打通,2. 以及如果有cur -> next的情况下,cur -> right -> next = cur -> left 的打通。完成后可以后移cur。第二个问题, 如果没有queue的情况下,如何发起下一层的遍历?因此必须要求在每次cur在最初发起本层遍历的时候,预先委托一个变量newStart记住这个下层起始,也就是cur -> left。cur每次接过newStart,newStart被向下遣派,循环也以此为标记终止:如果newStart 的位置为null,循环结束。
Complexity
Time complexity: O(n)
Space complexity: O(1)
易错点:
- cur -> left 查空
- cur -> next 查空
From discussion
class Solution {
public:
Node* connect(Node* root) {
// if (!root || !root -> left) return root;
Node* cur = root;
Node* newStart = root;
while (newStart) {
cur = newStart;
while (cur) {
if (cur -> left){
cur -> left -> next = cur -> right;
if (cur -> next) cur -> right -> next = cur -> next -> left;
cout << cur -> val << endl;
}
cur = cur -> next;
}
newStart = newStart -> left;
}
return root;
}
};
Java
void connect(TreeLinkNode *root) {
TreeLinkNode* level_start = root;
while(level_start!=NULL)
{
//curr is the first node in that level
TreeLinkNode* curr = level_start;
//Keep going to the right in that level
while(curr!=NULL)
{
if(curr->left!=NULL) curr->left->next=curr->right;
if(curr->right!=NULL && curr->next!=NULL) curr->right->next=curr->next->left;
curr = curr->next;
}
level_start=level_start->left;
}
}
方法3
层序遍历