题目 I:
Given a binary tree
struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *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.
- You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).
For example. Given the following perfect binary tree,
1 / \ 2 3 / \ / \ 4 5 6 7
After calling your function, the tree should look like:
1 -> NULL / \ 2 -> 3 -> NULL / \ / \ 4->5->6->7 -> NULL
解答:
要利用好“完美二叉树”这一前提条件,即每一层的节点个数为2的整数次幂,且有左子树时必有右子树。每到整数次幂的节点,next 就指向 NULL.
而且,处理1,然后处理2、3,然后处理4、5、6、7……顺序的访问方式,是不是很像数据结构:队列。
/**
* 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) {
if(root == NULL) return;
if(root->left == NULL && root->right == NULL) return;
queue<TreeLinkNode*> s;
s.push(root);
int i = 0;
int j = 1;
TreeLinkNode *tmp;
while(!s.empty())
{
tmp = s.front();
s.pop();
i++;
if(i == j)
{
i = 0;
j = j*2;
tmp->next = NULL;
}
else
{
tmp->next = s.front();
}
if(tmp->left)
{
s.push(tmp->left);
s.push(tmp->right);
}
}
}
};
但其实这种解法,不满足题目的额外要求:使用常数级空间。常数级空间的解法见下一题。
=========================================================================
题目 II:
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
解答:
这一题与上一题的不同在于,未必是满二叉树。如果不考虑常数级别空间,另外用一个数组记录每一层的节点个数后再使用队列同样可以。
但是,如果只能用常数级别空间,怎么办?
对于二叉树的遍历和连接,如果不能使用BFS(使用空间:队列)和DFS(使用空间:栈),怎么遍历?想想题目中结点多出来的指针:next.
解释此算法需要的三种指针:
- father 表示当前指针的父亲层指针,需要 father->next 的跳转,为了连接当前指针与邻接子树中的邻居(父亲为儿子的连接做工作,因为父亲层的 next 连接全部完成);
- cur 表示当前指针,这样进入邻接子树中的邻居节点,可以用 cur->next 指向;
- nextLev 表示 father 的另一种跳转:下一层的最左侧节点。如果 father->next 在同一层上不再有剩余节点,则需要跳转到 nextLev。跳转的同时,cur 与 nextLev 需要重新置为 NULL
/**
* 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) {
if(root == NULL || (root->left == NULL && root->right == NULL))
return;
TreeLinkNode *father = root;
TreeLinkNode *cur = NULL;
TreeLinkNode *nextLev = NULL;
while(father != NULL || nextLev != NULL)
{
if(father == NULL)
{
father = nextLev;
cur = NULL;
nextLev = NULL;
}
else
{
if(father->left != NULL && father->right != NULL)
{
if(nextLev == NULL)
nextLev = father->left;
father->left->next = father->right;
if(cur != NULL)
cur->next = father->left;
cur = father->right;
}
else if(father->left != NULL)
{
if(nextLev == NULL)
nextLev = father->left;
if(cur != NULL)
cur->next = father->left;
cur = father->left;
}
else if(father->right != NULL)
{
if(nextLev == NULL)
nextLev = father->right;
if(cur != NULL)
cur->next = father->right;
cur = father->right;
}
father = father->next;
}
}
return;
}
};