117. Populating Next Right Pointers in Each Node II
Medium
3365228Add to ListShare
Given a binary tree
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
.
Example 1:
Input: root = [1,2,3,4,5,null,7] Output: [1,#,2,3,#,4,5,7,#] Explanation: Given the above binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.
Example 2:
Input: root = [] Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 6000]
. -100 <= Node.val <= 100
Follow-up:
- You may only use constant extra space.
- The recursive approach is fine. You may assume implicit stack space does not count as extra space for this problem.
这两道题目相似,所以一起来看把!
题目是把每个node的next 指针指向同一层的下个元素。
既然是遍历树的每一层的问题,那问题就得用BFS来解决(breath 遍历)。
BFS的问题第一个想到用queue 来解决。
伪代码如下:
push root 到queue作为初始化
while(queue 不为空) {
1. 计算这一层有多少nodes
2. for循环一次把这一层的每个node出队列,并同时把每个node的左右子孩子入栈。(不要push null孩子进去哦)
3. 把每个节点记录下并赋值给指针tail,这样访问下个节点的时候就能更新tail的next指针了。
3. for循环结束,这一层的每个node也访问完了。queue里的节点也都更新为下一层的node了。
}
做完后就发现这两个题目的代码完全一样。 leetcode咋会这样那?
问题肯定不是那么简单。
肯定有更好的解法在等着我们那。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
if(root == NULL)
return root;
queue<Node*> myqueue;
myqueue.push(root);
while(!myqueue.empty()) {
Node * tail= NULL;
int size = myqueue.size();
for(int i=0;i<size;i++) {
Node * node = myqueue.front();
myqueue.pop();
if(tail != NULL)
tail -> next = node;
tail = node;
if(node->left)
myqueue.push(node->left);
if(node->right)
myqueue.push(node->right);
}
}
return root;
}
};
解法二:
如果题目规定不能用另外的数据结构来做这道题目,就不能用queue 了。
那就得一个个的更新node的next指针了。每个node的去更新next的时候,因为node 有可能不是同一个父亲,那么就得跨父节点去更新next。
为何不能遍历父节点的时候,去更新孩子节点的next指针哪?
按照这个思路,问题就有解法了。
于是伪代码如下
while( mostleft != NULL)
root = mostleft;
while(root != NULL) {
root->left->next = root->right
root->right->next = root->next->left
root = root->next
mostLeft = mostleft -> left;
对于完全二叉树算法就和伪代码一样。
对于不是完全二叉树,就得加很多判断来确定左右孩子是不是存在,next node中是不是有孩子以及mostleft 指向那个node等。
不过大概思路也一样。
伪代码基于上面的需要更改如下:
mostleft = root;
while( mostleft != NULL)
node = mostleft; -- node指向当前level的最左边的node
mostleft = NULL; -- mostleft 也得动态更新,因为已经不是完全二叉树了。
while(node != NULL) {
if(node ->left 存在)
如果mostleft为空,那么就把mostleft指向node->left
如果node->right 存在,那么就把node->left->next 指向node->right
else //这也就意味着next指针得指向父节点的兄弟的孩子了。
如果父节点的第一个兄弟节点没有孩子,那就得去找第二个兄弟节点的孩子。。。。
if(node ->right 存在)
如果mostleft为空,那么就把mostleft指向node->right
node的右孩子比较悲催,其next肯定得去父亲的兄弟节点里找他的表兄弟了。
如果父节点的第一个表兄弟节点没有孩子,那就得去找第二个兄弟节点的孩子。。。。
node= node->next;
代码如下:
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
if(root == NULL)
return NULL;
Node * head = root;
Node * mostLeft = root;
while(mostLeft != NULL) {
mostLeft = NULL;
while(root != NULL) {
if(root->left != NULL) {
if(mostLeft == NULL)
mostLeft = root->left;
if(root->right != NULL) {
root->left->next = root->right;
}
else {
Node* nextAvalibeNode = root->next;
while(nextAvalibeNode != NULL) {
if(nextAvalibeNode->left == NULL && nextAvalibeNode->right == NULL)
nextAvalibeNode = nextAvalibeNode->next;
else if(nextAvalibeNode->left != NULL) {
root->left->next = nextAvalibeNode->left;
break;
}
else if(nextAvalibeNode->right != NULL) {
root->left->next = nextAvalibeNode->right;
break;
}
}
}
}
if(root->right != NULL) {
if(mostLeft == NULL)
mostLeft = root->right;
Node* nextAvalibeNode = root->next;
while(nextAvalibeNode != NULL) {
if(nextAvalibeNode->left == NULL && nextAvalibeNode->right == NULL)
nextAvalibeNode = nextAvalibeNode->next;
else if(nextAvalibeNode->left != NULL) {
root->right->next = nextAvalibeNode->left;
break;
}
else if(nextAvalibeNode->right != NULL) {
root->right->next = nextAvalibeNode->right;
break;
}
}
}
root = root->next;
}
root = mostLeft;
}
return head;
}
};