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
.
Example:
Input: {"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{"$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{"$id":"5","left":{"$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{"$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1} Output: {"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":{"$id":"4","left":null,"next":{"$id":"5","left":null,"next":{"$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{"$id":"7","left":{"$ref":"5"},"next":null,"right":{"$ref":"6"},"val":3},"right":{"$ref":"4"},"val":2},"next":null,"right":{"$ref":"7"},"val":1} Explanation: Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B.
Note:
- You may only use constant extra space.
- Recursive approach is fine, implicit stack space does not count as extra space for this problem.
这道题实际上是树的层序遍历的应用,可以参考之前的博客 Binary Tree Level Order Traversal,既然是遍历,就有递归和非递归两种方法,最好两种方法都要掌握,都要会写。下面先来看递归的解法,由于是完全二叉树,所以若节点的左子结点存在的话,其右子节点必定存在,所以左子结点的 next 指针可以直接指向其右子节点,对于其右子节点的处理方法是,判断其父节点的 next 是否为空,若不为空,则指向其 next 指针指向的节点的左子结点,若为空则指向 NULL,代码如下:
解法一:
class Solution { public: Node* connect(Node* root) { if (!root) return NULL; if (root->left) root->left->next = root->right; if (root->right) root->right->next = root->next? root->next->left : NULL; connect(root->left); connect(root->right); return root; } };
对于非递归的解法要稍微复杂一点,但也不算特别复杂,需要用到 queue 来辅助,由于是层序遍历,每层的节点都按顺序加入 queue 中,而每当从 queue 中取出一个元素时,将其 next 指针指向 queue 中下一个节点即可,对于每层的开头元素开始遍历之前,先统计一下该层的总个数,用个 for 循环,这样当 for 循环结束的时候,该层就已经被遍历完了,参见代码如下:
解法二:
// Non-recursion, more than constant space class Solution { public: Node* connect(Node* root) { if (!root) return NULL; queue<Node*> q; q.push(root); while (!q.empty()) { int size = q.size(); for (int i = 0; i < size; ++i) { Node *t = q.front(); q.pop(); if (i < size - 1) { t->next = q.front(); } if (t->left) q.push(t->left); if (t->right) q.push(t->right); } } return root; } };
我们再来看下面这种碉堡了的方法,用两个指针 start 和 cur,其中 start 标记每一层的起始节点,cur 用来遍历该层的节点,设计思路之巧妙,不得不服啊:
解法三:
// Non-recursion, constant space class Solution { public: Node* connect(Node* root) { if (!root) return NULL; Node *start = root, *cur = NULL; while (start->left) { cur = start; while (cur) { cur->left->next = cur->right; if (cur->next) cur->right->next = cur->next->left; cur = cur->next; } start = start->left; } return root; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/116
类似题目:
Populating Next Right Pointers in Each Node II
参考资料:
https://leetcode.com/problems/populating-next-right-pointers-in-each-node/