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 pointer in each node的区别在于二叉树不是完美二叉树,所以每次的第一个结点不一定是沿着左子树的最左端一直向下。

方法一:

代码原出处没有解释,这里给出个人理解。上一题是这题的特殊情况,所以这题的代码也能通过上一题。

核心思想是:层次遍历。 在上一题中,我们记下当前行的下一行中最左端的结点作为起始点,是为了实现队列的层与层之间的转换功能,这里也同样用这种方式,但因上一题中是满二叉树,所以,我们只需在开头直接取就行,这里我们需判断当前行左右孩子中哪个存在就用哪个。这里值得注意的是,遇到4所在那一层时,cur=4的左右孩子都不存在时,直接取左右孩子中的一个,这时firNext依旧为NULL(因为不知道当前行中的左右孩子是否存在,所以,开始firNext定义为NULL),这时因为最左端的左右孩子都不存在,所以,不需要连接,然后我们在该行中移动cur,直达cur的左右孩子中至少一个存在,我们取存在的那个(若两个都存在,取左孩子)为下一行的最左端结点。

层与层之间的转换解决了,下面我们来解决行之间的移动。如图,若5为根结点的子树为3的右孩子,那如何连接4和5?像上一题中,4(身为2的左孩子),先连接2的右孩子,但其右孩子不存在啊?若是像上题中,那样:左连右,右连next的左,那中间就会有一个NULL !这时,我们定义一个遍历pre,让其完成在行中的穿针引线的作用:pre先指向2的左孩子4,因为2的右孩子不存在,所以,pre不动,直到遇到5.

最外层的while循环是层层之间的转化由firNext负责,层之间的连接由pre负责。

[Leetcode] Populating next right pointer in each node ii 填充每个节点的右指针-LMLPHP

/**
* Definition for binary tree with next pointer.
* struct TreeLinkNode {
* int val;
* TreeLinkNode *left, *right, *next;
* TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
* };
*/
class Solution {
public:
void connect(TreeLinkNode *root)
{
TreeLinkNode *cur=root;
while(cur)
{
TreeLinkNode *firNext=nullptr; //下一层的第一个结点
TreeLinkNode *prev=nullptr; //同一层中的前结点
while(cur)
{
if(firNext==nullptr)
firNext=cur->left?cur->left:cur->right;
if(cur->left)
{
if(prev)
prev->next=cur->left;
prev=cur->left;
}
if(cur->right)
{
if(prev)
prev->next=cur->right;
prev=cur->right;
}
cur=cur->next;
}
cur=firNext;
}
}
};

方法二:

递归,虽然不满题意,但有利于熟悉递归算法,依旧写在这。代码来源Grandyang博友。

// Recursion, more than constant space
class Solution {
public:
void connect(TreeLinkNode *root) {
if (!root) return;
TreeLinkNode *p = root->next;
while (p) {
if (p->left) {
p = p->left;
break;
}
if (p->right) {
p = p->right;
break;
}
p = p->next;
}
if (root->right) root->right->next = p;
if (root->left) root->left->next = root->right ? root->right : p;
connect(root->right);
connect(root->left);
}
};
04-17 08:21