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

算法-填充每个节点的下一个右侧节点指针

背景

  • 算法–填充每个节点的下一个右侧节点指针

  • 博主以代码随想录算法公开课进行学习

题目

  • 给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

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

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

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

示例 1:

1
2
3
输入:root = [1,2,3,4,5,6,7]
输出:[1,#,2,3,#,4,5,6,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化的输出按层序遍历排列,同一层节点由 next 指针连接,'#' 标志着每一层的结束。

示例 2:

1
2
入:root = []
输出:[]

思路

  • 与层序遍历一致
  • 从左到右用 next 指针连接起来,层最后一个节点的 next 指向 null

代码实现

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
32
33
34
35
36
37
38
39
40
41
class Solution {
public Node connect(Node root) {
// 1. 创建队列,用来做层序遍历(BFS)
Queue<Node> tmpQueue = new LinkedList<Node>();

// 2. 如果根节点不为空,先把根节点加入队列
if (root != null) tmpQueue.add(root);

// 3. 外层循环:只要队列不为空,就一直处理
while (tmpQueue.size() != 0){
// 【关键】记录当前这一层有多少个节点
// 必须先存起来,因为队列会不断变化
int size = tmpQueue.size();

// 4. 取出当前层的【第一个节点】
Node cur = tmpQueue.poll();

// 5. 把第一个节点的左右孩子加入队列(下一层用)
if (cur.left != null) tmpQueue.add(cur.left);
if (cur.right != null) tmpQueue.add(cur.right);

// 6. 内层循环:处理当前层剩下的所有节点(从第2个到最后一个)
for (int index = 1; index < size; index++){
// 取出下一个节点
Node next = tmpQueue.poll();

// 下一个节点的孩子入队
if (next.left != null) tmpQueue.add(next.left);
if (next.right != null) tmpQueue.add(next.right);

// 【核心】前一个节点.next = 后一个节点
cur.next = next;

// cur 向后移动,准备连接下一个节点
cur = next;
}
}
// 最后返回根节点
return root;
}
}

总结

  • 队列建议使用 ArrayDeque,比 LinkedList 内存占用更低,避免 LeetCode 内存超限
  • 不可在循环中直接使用 queue.size(),必须提前保存当前层大小