117_填充每个节点的下一个右侧节点指针II

117. 填充每个节点的下一个右侧节点指针 II

给定一个二叉树

1
2
3
4
5
6
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

填充它的每个 next指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next指针设置为 NULL

初始状态下,所有 next指针都被设置为 NULL

示例:

输入:root = [1,2,3,4,5,null,7]

输出:[1,#,2,3,#,4,5,7,#]

解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),'#' 表示每层的末尾。

思路:

和前面的116 填充每个节点的下一个右侧节点指针不同的是,现在给定的不是一个完美二叉树,所以递归的话不好实现。

这道题希望我们把二叉树各个层的点组织成链表,一个非常直观的思路是层次遍历。树的层次遍历基于广度优先搜索,它按照层的顺序遍历二叉树,在遍历第 i层前,一定会遍历完第 i - 1 层。

算法如下:初始化一个队列 q,将根结点放入队列中。当队列不为空的时候,记录当前队列大小为 n,从队列中以此取出 n 个元素并通过这 n 个元素拓展新节点。如此循环,直到队列为空。我们不难写出这样的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public:
Node* connect(Node* root) {
if(root == nullptr) return nullptr;
// 二叉树层次遍历
queue<Node*> q;
q.push(root);
while(!q.empty()){
int sz = q.size();
// pre 为表示访问下一个节点前一个节点
Node* pre = nullptr;
for(int i = 0; i < sz; i++){
Node* cur = q.front();
q.pop();
// 链接当前层所有节点的 next 指针
if(pre != nullptr){
pre->next = cur;
}
pre = cur;
// 将下一层节点装入队列
if(cur->left != nullptr){
q.push(cur->left);
}
if(cur->right != nullptr){
q.push(cur->right);
}
}
}
return root;
}
};