今日算法随笔:填充每个节点的下一个右侧节点指针 II
题目描述
给定一个二叉树,填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。初始状态下,所有 next 指针都被设置为 NULL。
示例:
输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:按层序遍历,'#' 表示每一层的末尾。
思路
层次遍历
这道题的核心是按层次遍历二叉树,并将每一层的节点通过 next 指针连接起来。由于树的结构不一定是完美二叉树,每个节点的左右子树数量可能不同,导致每层节点数量不均匀。因此,我们不能简单地直接使用完全二叉树的解法,而是需要根据当前节点的左右子节点来动态连接它们。
解题过程
方法运用
我们需要逐层遍历二叉树并构建 next 指针。在遍历时,使用以下几点策略:
从左到右遍历当前层节点:
- 对于每个节点,我们检查它是否有左子节点和右子节点。如果存在子节点,依次连接它们。
使用
next指针帮助跨节点连接:- 在跨越同一层不同父节点时(即当前节点的右子节点和下一个节点的左子节点),可以利用上一层已经构建好的
next指针,来顺利访问该层的其他节点。
- 在跨越同一层不同父节点时(即当前节点的右子节点和下一个节点的左子节点),可以利用上一层已经构建好的
构建下一层的连接关系:
- 遍历当前层时,将下一层的节点依次连接起来,并通过虚拟节点
dummy来指向下一层的第一个节点。
- 遍历当前层时,将下一层的节点依次连接起来,并通过虚拟节点
遍历完一层后进入下一层:
- 处理完当前层后,我们通过
dummy.next找到下一层的第一个节点,然后继续处理这一层,直到所有层遍历完毕。
- 处理完当前层后,我们通过
代码实现
下面是该算法的完整 Java 实现:
class Solution {
public Node connect(Node root) {
if (root == null) {
return null;
}
// 从当前层的头开始
Node currentLevel = root;
while (currentLevel != null) {
Node dummy = new Node(0); // 虚拟头节点,方便处理下一层的连接
Node prev = dummy; // 用来连接下一层节点的指针
Node curr = currentLevel; // 当前层的节点
while (curr != null) {
if (curr.left != null) {
prev.next = curr.left;
prev = prev.next;
}
if (curr.right != null) {
prev.next = curr.right;
prev = prev.next;
}
curr = curr.next; // 移动到当前层的下一个节点
}
currentLevel = dummy.next; // 进入下一层
}
return root;
}
}
代码细节
Node类:Node类代表二叉树的节点,每个节点包含val(节点值),left(左子节点),right(右子节点)和next(右侧节点的指针)。
主逻辑:
currentLevel变量用于追踪每一层的开始节点。- 通过
dummy虚拟节点和prev指针将下一层的节点按顺序连接起来。 - 遍历完当前层后,
dummy.next就会指向下一层的第一个节点,赋值给currentLevel以开始处理下一层。
循环控制:
- 内层
while (curr != null)循环用于遍历当前层的所有节点,并连接它们的子节点。 - 外层
while (currentLevel != null)循环用于逐层处理,直到所有节点都完成连接。
- 内层
常见问题解答
1. 为什么 currentLevel = dummy.next 能进入下一层?
dummy 是一个虚拟头节点,它用于帮助我们方便地连接当前层的子节点,即下一层的所有节点。当遍历当前层时,每次找到一个子节点,就把它连接到 dummy 的链表中(由 prev.next 来完成)。因此,dummy.next 最终会指向下一层的第一个节点。通过 currentLevel = dummy.next,我们就能顺利进入下一层的第一个节点,开始处理下一层。
2. 为什么需要 dummy 节点?
dummy 节点的作用是简化逻辑。在处理下一层节点时,我们需要将它们串起来,并且要记录下一层的第一个节点。使用 dummy 节点可以方便地处理这种情况,它始终指向下一层的开始位置,无需特殊处理第一个节点与其他节点的连接,简化了代码。
3. 该算法的时间和空间复杂度如何?
- 时间复杂度:O(n),因为每个节点只会被访问一次。
- 空间复杂度:O(1),除了递归栈之外,使用的额外空间是常数级别的。
今日算法随笔:填充每个节点的下一个右侧节点指针 II的更多相关文章
- [leetcode-117]填充每个节点的下一个右侧节点指针 II
(1 AC) 填充每个节点的下一个右侧节点指针 I是完美二叉树.这个是任意二叉树 给定一个二叉树 struct Node { int val; Node *left; Node *right; Nod ...
- [LeetCode] 116. 填充每个节点的下一个右侧节点指针
题目链接 : https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/ 题目描述: 给定一个完美二叉树 ...
- Java实现 LeetCode 117 填充每个节点的下一个右侧节点指针 II(二)
117. 填充每个节点的下一个右侧节点指针 II 给定一个二叉树 struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每 ...
- Java实现 LeetCode 116 填充每个节点的下一个右侧节点指针
116. 填充每个节点的下一个右侧节点指针 给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点.二叉树定义如下: struct Node { int val; Node *left ...
- LeetCode OJ:Populating Next Right Pointers in Each Node II(指出每一个节点的下一个右侧节点II)
Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...
- 117. 填充每个节点的下一个右侧节点指针 II
Q: 给定一个二叉树 struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右 ...
- leetcode117. 填充每个节点的下一个右侧节点指针 II
给定一个二叉树struct Node { int val; Node *left; Node *right; Node *next;}填充它的每个 next 指针,让这个指针指向其下一个右侧节 ...
- leetcode 117. 填充每个节点的下一个右侧节点指针 II(二叉树,DFS)
题目链接 https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/ 题目大意 给定一个二叉树 s ...
- 【LeetCode】116. 填充每个节点的下一个右侧节点指针 Populating Next Right Pointers in Each Node 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...
- leetcode 116填充每个节点的下一个右侧节点指针
time O(n) ,sapce O(n) /* // Definition for a Node. class Node { public: int val; Node* left; Node* r ...
随机推荐
- 【实操记录】MySQL二进制安装包部署
截至2023年11月2日,MySQL社区版最新版本是8.0.35,本文详细描述了采用二进制安装的各个步骤,具有较强的参考意义,基本可作为标准步骤实施. ■ 下载数据库介质 社区版的下载地址为oracl ...
- VPS测试脚本,网络线路,路由测试,流媒体服务器测试脚本
收集了一些服务器测试脚本,测试性能,网络以及解锁Netflix等服务.记录收集一下,特此记录. yabs测试脚本wget -qO- yabs.sh | bash 老外比较爱用的服务器性能测试脚本. ...
- 完美卸载Docker
1,删除docker所在目录 rm -rf /etc/docker rm -rf /run/docker rm -rf /var/lib/dockershim rm -rf /var/lib/dock ...
- oeasy教您玩转python - 012 - # 刷新时间
刷新时间 回忆上次内容 通过搜索 我们学会 import 导入 time 了 time 是一个 module import 他可以做和时间相关的事情 time.time() 得到当前时间戳 tim ...
- 封装的grid控件
class CGridCtrl : public CWnd { DECLARE_DYNAMIC(CGridCtrl) public: void Create(CWnd* pParent, DWORD ...
- 【SpringCloud】Re04 Gateway
微服务网关: 1.身份认证 和 权限校验 2.服务路由.负载均衡 3.请求限流 搭建服务网关: 网关是一个独立的服务,同样需要被注册中心注册到,这里依然使用的是Nacos <?xml versi ...
- DirectX9(D3D9)游戏开发:高光时刻录制和共享纹理的踩坑
共享纹理 老游戏使用directx9无法直接与cc高光sdk(d3d11)对接,但是d3d9ex有共享纹理,我们通过共享纹理把游戏画面共享给cc录制,记录一些踩坑的笔记. 共享纹理示例: // 初始化 ...
- 关于Isaac Gym的两个版本比较:IsaacGymEnvs/omni.isaac.gym
原文地址: https://zhuanlan.zhihu.com/p/590468555 重点: IsaacGymEnvs (IGE)和 omni.isaac.gym (OIG)是两个东西. 原文内容 ...
- 全球最大开源模型Grok-1 —— 马斯克的大模型
Grok官网: https://grok.x.ai/
- mini_imagenet 数据集生成工具
最近在看小样本方面的论文,发现这个mini_imagenet这个数据集比较常用,但是却不好找,找了半天也没有找到,最后在找到了这样的答案: 小样本学习(Few shot learning)标准数据集( ...