LeetCode 116. 填充每个节点的下一个右侧节点指针
题目描述


题意分析
输入是一棵完美二叉树:每个非叶节点都有两个孩子,所有叶子位于同一层。需要为每个节点的
next指向同层紧邻右侧的节点,每层最右节点指向空,原左右孩子连接保持不变。题目保证初始
next都为空。普通层序遍历可以借助队列寻找相邻节点,但这里树形完整,可以直接利用已经连好的当前层,建立下一层的连接,实现常数额外空间。
解法:利用已连接层原地串联下一层
核心思路
[!blue]
用
leftmost保存当前层最左节点,每轮开始时,这一层的next已经连接完整。根层只有一个节点,初始next为空,天然满足这个条件,因此可以从根层开始。沿当前层的
next从左到右访问父节点cur。下一层相邻节点的关系只有两类:同一个父节点的左孩子后面是右孩子,设置cur.left.next = cur.right;这个右孩子后面则是相邻父节点的左孩子,若cur.next存在,就设置cur.right.next = cur.next.left。两类连接覆盖了下一层的全部相邻位置。当前层最右父节点没有后继,它的右孩子也是下一层最右节点,不再设置后继,保留初始的空指针即可。处理时只改孩子的
next,不会影响正在用来横向遍历的当前层连接。整层完成后,下一层已经连好,将
leftmost移到它的左孩子,再重复相同过程。完美树保证只要最左节点有孩子,这一层的所有父节点就都有两个孩子,可以安全使用上述直接连接。当
leftmost.left为空,当前层就是叶子层,不需要再连接下一层,循环结束。空树在入口返回,只有根节点时也会自然跳过外层循环。
解题步骤
- 根为空时直接返回空,否则令
leftmost = root。- 当前层仍有孩子时,从
leftmost开始沿next横向遍历。- 对每个父节点,先把左孩子的
next连到右孩子。- 若存在相邻父节点,再把右孩子的
next连到它的左孩子。- 当前层全部处理后,令
leftmost = leftmost.left,进入刚连接好的下一层,最后返回原根。
代码实现
class Solution {
public Node connect(Node root) {
if (root == null) {
return null;
}
Node leftmost = root;
// 只在下一层存在时连接孩子,到叶子层即停止
while (leftmost.left != null) {
Node cur = leftmost;
// 当前层已通过 next 串好,用它横向遍历并连接下一层。
while (cur != null) {
cur.left.next = cur.right;
if (cur.next != null) {
// 跨父节点的接缝依赖当前层已经连好的横向链接
cur.right.next = cur.next.left;
}
cur = cur.next;
}
// 下一层刚刚连接完成,从其最左节点开始下一轮
leftmost = leftmost.left;
}
return root;
}
}
func connect(root *Node) *Node {
if root == nil {
return nil
}
leftmost := root
// 只在下一层存在时连接孩子,到叶子层即停止
for leftmost.Left != nil {
cur := leftmost
// 当前层已通过 Next 串好,用它横向遍历并连接下一层。
for cur != nil {
cur.Left.Next = cur.Right
if cur.Next != nil {
// 跨父节点的接缝依赖当前层已经连好的横向链接
cur.Right.Next = cur.Next.Left
}
cur = cur.Next
}
// 下一层刚刚连接完成,从其最左节点开始下一轮
leftmost = leftmost.Left
}
return root
}
复杂度分析
- 时间复杂度:$O(n)$,各非叶节点作为父节点处理一次,叶节点无须再展开。
- 空间复杂度:$O(1)$,两个遍历指针。
关键点总结
[!green]
- 当前层的答案同时充当遍历下一层的工具。
- 完美树条件保证同层父节点都有两个孩子。
易错点总结
[!yellow]
- 只连接同父兄弟:会遗漏不同父节点之间的接缝,下一层不能完整横向遍历。
- 跨父连接不检查
cur.next:最右父节点没有后继,直接读取它的孩子会访问空指针。- 到叶子层仍继续展开:叶子没有左右孩子,外层应在下一层不存在时停止。
- 把写法用于任意二叉树:直接连接依赖完美树条件,缺失孩子时不能照搬。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 117. 填充每个节点的下一个右侧节点指针 II | 中等 | 本题完美二叉树可直接跨父节点连邻居,原题缺失节点较多,需要动态寻找下一层可用节点。 |
| 102. 二叉树的层序遍历 | 中等 | 层序遍历可直观定位同层后继,本题还可利用已建next链省掉队列。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!