二叉树题目:填充每个结点的下一个右侧结点指针 II

news/2024/11/18 3:39:52/

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
      • 进阶
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法三
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:填充每个结点的下一个右侧结点指针 II

出处:117. 填充每个结点的下一个右侧结点指针 II

难度

4 级

题目描述

要求

给定一个二叉树,定义如下:

struct Node {int val;Node *left;Node *right;Node *next;
}

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

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

示例

示例 1:

示例 1

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

示例 2:

输入: root = [] \texttt{root = []} root = []
输出: [] \texttt{[]} []

数据范围

  • 树中结点数目在范围 [0, 6000] \texttt{[0, 6000]} [0, 6000]
  • -100 ≤ Node.val ≤ 100 \texttt{-100} \le \texttt{Node.val} \le \texttt{100} -100Node.val100

进阶

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不计入额外的空间。

解法一

思路和算法

由于每个结点的下一个右侧结点一定和该结点位于同一层,因此只要在同一层的结点之间填充下一个右侧结点指针即可。可以使用层序遍历实现。

层序遍历的方法为从根结点开始依次遍历每一层的结点,同一层的结点的遍历顺序为从左到右。在层序遍历的过程中需要区分不同结点所在的层,确保每一轮访问的结点为同一层的全部结点。

使用队列存储待访问的结点,初始时将根结点入队列。每一轮访问结点之前首先得到队列内的元素个数,然后访问这些结点,并将这些结点的非空子结点入队列。该做法可以确保每一轮访问的结点为同一层的全部结点。

每次访问结点时,将待访问的结点出队列。如果当前访问的结点不是当前层的最后一个结点,则此时的队首元素即为当前结点的下一个右侧结点(注意当前结点已经出队列),将当前结点的下一个右侧结点指针指向队首元素。

遍历结束之后返回根结点,此时二叉树中每个结点的下一个右侧结点指针都被填充。

代码

class Solution {public Node connect(Node root) {if (root == null) {return root;}Queue<Node> queue = new ArrayDeque<Node>();queue.offer(root);while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; i++) {Node node = queue.poll();if (i < size - 1) {node.next = queue.peek();}if (node.left != null) {queue.offer(node.left);}if (node.right != null) {queue.offer(node.right);}}}return root;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是队列空间,队列内元素个数不超过 n n n

解法二

思路和算法

也可以使用深度优先搜索填充每个结点的下一个右侧结点指针。具体做法是使用前序遍历,依次访问二叉树的根结点、左子树和右子树,由于前序遍历满足同一层结点被访问的顺序为从左到右,因此可以在前序遍历过程中填充每个结点的下一个右侧结点指针。由于每个结点的下一个右侧结点一定和该结点位于同一层,因此需要使用哈希表存储每一层已经访问过的的最右侧结点。

前序遍历过程中,对于每个结点,执行如下操作。

  1. 如果当前结点所在层已经有被访问过的结点,则从哈希表中得到该层已经访问过的最右侧结点,并将已经访问过的最右侧结点的下一个右侧结点指针指向当前结点。如果当前结点所在层没有被访问过的结点,则跳过这一步。

  2. 将哈希表中当前结点所在层已经访问过的最右侧结点设为当前结点。

遍历结束之后返回根结点,此时二叉树中每个结点的下一个右侧结点指针都被填充。

代码

class Solution {public Node connect(Node root) {Map<Integer, Node> rightmost = new HashMap<Integer, Node>();Deque<Node> nodeStack = new ArrayDeque<Node>();Deque<Integer> depthStack = new ArrayDeque<Integer>();Node node = root;int depth = 0;while (!nodeStack.isEmpty() || node != null) {while (node != null) {if (rightmost.containsKey(depth)) {rightmost.get(depth).next = node;}rightmost.put(depth, node);nodeStack.push(node);depthStack.push(depth);node = node.left;depth++;}node = nodeStack.pop().right;depth = depthStack.pop() + 1;}return root;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度主要是哈希表和栈空间,取决于二叉树的高度,最坏情况下二叉树的高度是 O ( n ) O(n) O(n)

解法三

思路和算法

为了将空间复杂度降到 O ( 1 ) O(1) O(1),需要使用其他方法遍历二叉树并填充每个结点的下一个右侧结点指针。

如果根结点为空或者根结点为叶结点,则不需要填充任何结点的下一个右侧结点指针,直接返回原始二叉树。以下只考虑根结点不为空且不为叶结点的情况。

规定根结点所在层是第 0 0 0 层,从根结点开始填充每一层的下一个右侧结点指针。由于根结点所在层没有其他结点,因此不需要填充根结点的下一个右侧结点指针。

对于 k ≥ 0 k \ge 0 k0,当第 k k k 层的全部结点的下一个右侧结点指针填充完毕时,第 k k k 层的全部结点组成一个单向链表,每个结点的下一个右侧结点指针指向单向链表中的后一个结点。

当第 k k k 层有结点时,第 k k k 层的全部结点的子结点即为第 k + 1 k + 1 k+1 层的全部结点。从左到右依次遍历第 k k k 层的每个结点,对于每个结点依次得到其左子结点和右子结点,则遍历子结点的顺序为从左到右遍历第 k + 1 k + 1 k+1 层的所有结点的顺序,遍历子结点的过程中即可填充第 k + 1 k + 1 k+1 层的所有结点的下一个右侧结点指针。

填充下一个右侧结点指针需要维护两项信息,一是同一层结点的最左侧结点,二是上一个被访问的结点。这两项信息都可以在遍历过程中完成,具体做法如下。

  1. 将第 k + 1 k + 1 k+1 层的第一个被访问的结点设为第 k + 1 k + 1 k+1 层结点的最左侧结点。

  2. 如果上一个被访问的子结点不为空,则将上一个被访问的子结点的下一个右侧结点指针指向当前子结点。

  3. 将当前子结点赋给上一个被访问的子结点。

当第 k k k 层遍历完毕且第 k + 1 k + 1 k+1 层的下一个右侧结点指针填充完毕时,移动到第 k + 1 k + 1 k+1 层的最左侧结点,继续填充其余层的下一个右侧结点指针。当遍历到的层没有结点时,结束操作,此时所有结点的下一个右侧结点指针填充完毕。

代码

class Solution {Node nextStart;Node prev;public Node connect(Node root) {if (root == null) {return root;}Node start = root;while (start != null) {Node node = start;nextStart = null;prev = null;while (node != null) {update(node.left);update(node.right);node = node.next;}start = nextStart;}return root;}public void update(Node curr) {if (curr == null) {return;}if (nextStart == null) {nextStart = curr;}if (prev != null) {prev.next = curr;}prev = curr;}
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。每个结点都被访问一次。

  • 空间复杂度: O ( 1 ) O(1) O(1)


http://www.ppmy.cn/news/1094268.html

相关文章

蚂蚁集团正式开源万亿规模图学习系统AGL

9月7日下午&#xff0c;上海外滩大会“融合机器学习与运筹优化”论坛上&#xff0c;蚂蚁集团正式开源图学习系统Ant Graph Learning &#xff08;AGL&#xff09;&#xff0c;这是行业首个通用的工业图学习系统。 图片说明&#xff1a;论坛上&#xff0c;蚂蚁集团正式开源了图学…

js去除字符串空格的几种方式

方法1&#xff1a;(最常用)全部去除掉空格 var str abc d e f g ; function trim(str) { var reg /[\t\r\f\n\s]*/g; if (typeof str string) { var trimStr str.replace(reg,); } console.lo…

2023高教社杯 国赛数学建模E题思路 - 黄河水沙监测数据分析

1 赛题 E 题 黄河水沙监测数据分析 黄河是中华民族的母亲河。研究黄河水沙通量的变化规律对沿黄流域的环境治理、气候变 化和人民生活的影响&#xff0c; 以及对优化黄河流域水资源分配、协调人地关系、调水调沙、防洪减灾 等方面都具有重要的理论指导意义。 附件 1 给出了位…

2023-09-07工作心得:String 和 LocalDate 的比较

1、SQL查询时间 如果根据某个日期区间检索&#xff1a; 假设有张t_order表&#xff0c;其中有个字段 create_time 在数据库里的格式是”yyyy-MM-dd HH:mm:ss“ 如果我在前端&#xff0c;选择2023-09-06-2023-09-07&#xff0c;这个区间&#xff0c;其实我期待的是查出这两天…

基于Delft3D模型水体流动、污染物对流扩散、质点运移、溢油漂移及地表水环境报告编制教程

详情点击链接&#xff1a;基于Delft3D模型水体流动、污染物对流扩散、质点运移、溢油漂移及地表水环境报告编制教程 前沿 Delft3D计算网格构建 Delft3D水动力数值模拟 Delft3D污染物对流扩散数值模拟 一&#xff0c;Delft3D软件及建模 1.1地表水数值模拟常用软件、优势、如何…

2023高教社杯 国赛数学建模D题思路 - 圈养湖羊的空间利用率

1 赛题 D 题 圈养湖羊的空间利用率 规模化的圈养养殖场通常根据牲畜的性别和生长阶段分群饲养&#xff0c; 适应不同种类、不同阶段 的牲畜对空间的不同要求&#xff0c;以保障牲畜安全和健康&#xff1b;与此同时&#xff0c;也要尽量减少空间闲置所造成 的资源浪费。在实际…

智慧工厂的未来:视频+数字孪生与工业4.0的融合

视频数字孪生技术在智慧工厂项目中具有广泛的应用&#xff0c;为生产制造提供了前所未有的机会和优势。下面将探讨数字孪生技术在智慧工厂项目中的多个应用场景。 数字孪生技术的首要应用之一是生产流程优化。通过将现实世界的工厂映射到数字孪生模型中&#xff0c;制造…

6个免费图片素材库,高清无水印、无版权

推荐6个免费高清图片素材库&#xff0c;商用也可以&#xff0c;无需担心版权问题&#xff0c;收藏走一波~ 1、菜鸟图库 https://www.sucai999.com/pic.html?vNTYwNDUx 网站主要为新手设计师提供免费素材&#xff0c;这些素材的质量都很高&#xff0c;类别也很多&#xff0c;…