二叉树题目:从前序遍历还原二叉树

文章目录

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

题目

标题和出处

标题:从前序遍历还原二叉树

出处:1028. 从前序遍历还原二叉树

难度

6 级

题目描述

要求

我们从二叉树的根结点 root \texttt{root} root 开始深度优先搜索。

在遍历中的每个结点处,我们输出 D \texttt{D} D 条短划线(其中 D \texttt{D} D 是该结点的深度),然后输出该结点的值。如果结点的深度为 D \texttt{D} D,则其子结点的深度为 D + 1 \texttt{D + 1} D + 1。根结点的深度为 0 \texttt{0} 0

如果结点只有一个子结点,那么保证该子结点为左子结点。

给出遍历的输出 traversal \texttt{traversal} traversal,还原树并返回其根结点 root \texttt{root} root

示例

示例 1:

示例 1

输入: traversal = "1-2--3--4-5--6--7" \texttt{traversal = "1-2--3--4-5--6--7"} traversal = "1-2--3--4-5--6--7"
输出: [1,2,5,3,4,6,7] \texttt{[1,2,5,3,4,6,7]} [1,2,5,3,4,6,7]

示例 2:

示例 2

输入: traversal = "1-2--3---4-5--6---7" \texttt{traversal = "1-2--3---4-5--6---7"} traversal = "1-2--3---4-5--6---7"
输出: [1,2,5,3,null,6,null,4,null,7] \texttt{[1,2,5,3,null,6,null,4,null,7]} [1,2,5,3,null,6,null,4,null,7]

示例 3:

示例 3

输入: traversal = "1-401--349---90--88" \texttt{traversal = "1-401--349---90--88"} traversal = "1-401--349---90--88"
输出: [1,401,null,349,88,90] \texttt{[1,401,null,349,88,90]} [1,401,null,349,88,90]

数据范围

  • 树中结点数目在范围 [1, 1000] \texttt{[1, 1000]} [1, 1000]
  • 1 ≤ Node.val ≤ 10 9 \texttt{1} \le \texttt{Node.val} \le \texttt{10}^\texttt{9} 1Node.val109

解法

思路和算法

给定的字符串包含每个结点的值和结点所在深度。根结点所在深度为 0 0 0,其余结点所在深度都大于 0 0 0

由于给定的字符串是二叉树的前序遍历序列,因此对于遍历到的每个结点,如果其层数为 depth \textit{depth} depth depth > 0 \textit{depth} > 0 depth>0),其父结点一定是已经遍历的结点中的最后一个访问过的层数为 depth − 1 \textit{depth} - 1 depth1 的结点。如果父结点的左子结点为空,则当前结点作为父结点的左子结点,否则当前结点作为父结点的右子结点。

为了定位到最后一个访问过的上一层结点,需要使用栈存储结点。栈内结点从栈底到栈顶的深度依次递增,根结点位于栈底。

首先从给定的字符串中得到根结点值,创建根结点,并将根结点入栈。继续遍历字符串的其余部分,对于每个结点,执行如下操作。

  1. 根据短划线数量得到结点所在深度 depth \textit{depth} depth,根据短划线后的数值得到结点值 val \textit{val} val,使用结点值 val \textit{val} val 创建当前结点。

  2. 当前结点的父结点的深度为 depth − 1 \textit{depth} - 1 depth1。如果栈内元素个数大于 depth \textit{depth} depth,则栈顶结点的深度与父结点的深度不同,因此将栈顶结点出栈。重复出栈操作直到栈内元素个数等于 depth \textit{depth} depth,此时栈顶结点的深度为 depth − 1 \textit{depth} - 1 depth1

  3. 此时栈顶结点为当前结点的父结点。判断父结点的左子结点是否为空,如果父结点的左子结点为空则将当前结点设为父结点的左子结点,否则将当前结点设为父结点的右子结点。

  4. 将当前结点入栈。

重复上述操作,直到字符串遍历结束。遍历结束之后返回根结点,即为还原的二叉树。

以下是示例 1 的计算过程。

  1. 创建根结点 1 1 1,深度为 0 0 0。将结点 1 1 1 入栈, stack = [ 1 ] \textit{stack} = [1] stack=[1],其中左边为栈底,右边为栈顶,栈内元素为结点,此处用数字表示结点且省略父结点和子结点的关系。

  2. 创建结点 2 2 2,深度为 1 1 1。由于栈内元素个数等于 1 1 1,因此将结点 2 2 2 作为栈顶结点 1 1 1 的左子结点,将结点 2 2 2 入栈, stack = [ 1 , 2 ] \textit{stack} = [1, 2] stack=[1,2]

  3. 创建结点 3 3 3,深度为 2 2 2。由于栈内元素个数等于 2 2 2,因此将结点 3 3 3 作为栈顶结点 2 2 2 的左子结点,将结点 3 3 3 入栈, stack = [ 1 , 2 , 3 ] \textit{stack} = [1, 2, 3] stack=[1,2,3]

  4. 创建结点 4 4 4,深度为 2 2 2。由于栈内元素个数大于 2 2 2,因此将结点 3 3 3 出栈,此时栈内元素个数等于 2 2 2,将结点 4 4 4 作为栈顶结点 2 2 2 的右子结点,将结点 4 4 4 入栈, stack = [ 1 , 2 , 4 ] \textit{stack} = [1, 2, 4] stack=[1,2,4]

  5. 创建结点 5 5 5,深度为 1 1 1。由于栈内元素个数大于 1 1 1,因此将结点 4 4 4 2 2 2 出栈,此时栈内元素个数等于 1 1 1,将结点 5 5 5 作为栈顶结点 1 1 1 的右子结点,将结点 5 5 5 入栈, stack = [ 1 , 5 ] \textit{stack} = [1, 5] stack=[1,5]

  6. 创建结点 6 6 6,深度为 2 2 2。由于栈内元素个数等于 2 2 2,因此将结点 6 6 6 作为栈顶结点 5 5 5 的左子结点,将结点 6 6 6 入栈, stack = [ 1 , 5 , 6 ] \textit{stack} = [1, 5, 6] stack=[1,5,6]

  7. 创建结点 7 7 7,深度为 2 2 2。由于栈内元素个数大于 2 2 2,因此将结点 6 6 6 出栈,此时栈内元素个数等于 2 2 2,将结点 7 7 7 作为栈顶结点 5 5 5 的右子结点,将结点 7 7 7 入栈, stack = [ 1 , 5 , 7 ] \textit{stack} = [1, 5, 7] stack=[1,5,7]

  8. 遍历结束,返回根结点 1 1 1

代码

class Solution {public TreeNode recoverFromPreorder(String traversal) {Deque<TreeNode> stack = new ArrayDeque<TreeNode>();int rootVal = 0;int length = traversal.length();int index = 0;while (index < length && Character.isDigit(traversal.charAt(index))) {rootVal = rootVal * 10 + traversal.charAt(index) - '0';index++;}TreeNode root = new TreeNode(rootVal);stack.push(root);while (index < length) {int depth = 0;while (traversal.charAt(index) == '-') {depth++;index++;}int val = 0;while (index < length && Character.isDigit(traversal.charAt(index))) {val = val * 10 + traversal.charAt(index) - '0';index++;}TreeNode node = new TreeNode(val);while (stack.size() > depth) {stack.pop();}TreeNode parent = stack.peek();if (parent.left == null) {parent.left = node;} else {parent.right = node;}stack.push(node);}return root;}
}

复杂度分析

  • 时间复杂度: O ( m ) O(m) O(m),其中 m m m 是字符串 traversal \textit{traversal} traversal 的长度。需要遍历字符串一次还原二叉树,对于二叉树中的每个结点,最多入栈和出栈各一次。由于二叉树的结点数 n n n 一定不超过字符串的长度 m m m,因此总时间复杂度是 O ( m ) O(m) O(m)

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/222182.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5键键盘的输出 - 华为OD统一考试

OD统一考试 题解&#xff1a; Java / Python / C 题目描述 有一个特殊的 5键键盘&#xff0c;上面有 a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键。 a 键在屏幕上输出一个字母 a; ctrl-c 将当前选择的字母复制到剪贴板; ctrl-x 将当前选择的 字母复制到剪贴板&#xff0c;并清空选择…

机器视觉【1】相机的成像(畸变)模型

零、前言 很久没写文章&#xff0c;简单唠一唠。 不知道巧合还是蜀道同归&#xff0c;部门领导设定了些研究课题&#xff0c;用于公司部门员工的超前发展&#xff0c;该课题是“2D to 3D的三维重建”&#xff0c;这一块刚好是我个人看中的一个大方向&#xff0c;所以就有了这…

leetcode-21-合并两个有序链表(C语言实现)

题目&#xff1a; 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出…

一文读懂FastAPI:Python 开发者的福音

FastAPI是一个基于Python的现代化Web框架&#xff0c;它提供了快速、简单和高性能的方式来构建API。 它结合了Python的静态类型检查和自动化文档生成的功能&#xff0c;使得开发API变得更加容易和高效。 下面将介绍如何使用FastAPI快速开发接口&#xff0c;并且利用自动生成的…

《LeetCode力扣练习》代码随想录——字符串(KMP算法学习补充——针对next数组构建的回退步骤进行解释)

《LeetCode力扣练习》代码随想录——字符串&#xff08;KMP算法学习补充——针对next数组构建的回退步骤进行解释&#xff09; 学习路径 代码随想录&#xff1a;28. 实现 strStr() CSDN&#xff1a;【详解】KMP算法——多图&#xff0c;多例子&#xff08;c语言&#xff09; …

【Qt之QNetworkAccessManager】概述及示例

概述 QNetworkAccessManager类允许应用程序发送网络请求和接收应答 网络访问API是围绕一个QNetworkAccessManager对象构建的&#xff0c;该对象为它发送的请求保存通用配置和设置。它包含代理和缓存配置&#xff0c;以及与此类问题相关的信号&#xff0c;以及可用于监视网络操…

Antd Select 添加中框

默认antd 的 Select中间并没有竖框&#xff0c;但是ui design设计了&#xff0c;所以记录一下如何添加 默认&#xff1a; CSS&#xff1a; .custom-select-suffix-icon {display: flex;align-items: center; }.custom-select-suffix-icon::before {content: ;height: 31px; …

什么品牌的猫粮比较好?主食冻干猫粮品牌十大排行

咱们养猫人每天最愁的就是咋给自家猫咪选一款优质的猫粮&#xff0c;让猫主子吃了健健康康的。早些年大多养猫人的标准就是盯着进口的买&#xff0c;所以之前进口猫粮的销量一直遥遥领先&#xff0c;感觉品控也严&#xff0c;也就放心大胆的冲进口猫粮了&#xff0c;但近期百利…

flink中如何把DB大表的配置数据加载到内存中对数据流进行增强处理

背景 在处理flink的数据流时&#xff0c;比如处理商品流时&#xff0c;一般我们从kafka中只拿到了商品id&#xff0c;此时我们需要把商品的其他配置信息比如品牌品类等也拿到&#xff0c;此时就需要关联上外部配置表来达到丰富数据流的目的&#xff0c;如果外部配置表很大&…

我的隐私计算学习——隐私集合求交(1)

笔记内容来自多本书籍、学术资料、白皮书及ChatGPT等工具&#xff0c;经由自己阅读后整理而成。 &#xff08;一&#xff09;PSI的介绍 隐私计算关键技术&#xff1a;隐私集合求交&#xff08;PSI&#xff09;原理介绍 隐私计算关键技术&#xff1a;隐私集合求交&#xff08…

事务--03---TCC空回滚、悬挂、幂等解决方案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 Seata TCC 模式设计思路TCC存在的问题1、空回滚以及解决方案解决方案&#xff1a; 2、幂等问题以及解决方案解决方案&#xff1a; 3、悬挂问题以及解决方案解决方案…

PCIe设备热插拔-理论篇

硬件层面理解热插拔 PRSNT1#和PRSNT2#信号与PCIe设备的热插拔相关。在基于PCIe总线的Add-in 卡中&#xff0c;PRSNT1# 和PRSNT2#信号直接相连&#xff0c;而在处理器主板中&#xff0c;PRSNT1#信号接地&#xff0c;而PRSNT2#信号通过上 拉电阻接为高。 不同的处理器系统处理PC…

【Mysql】InnoDB的表空间(九)

概述 表空间是一个在 InnoDB 中比较抽象的概念&#xff0c;对于系统表空间来说&#xff0c;对应着文件系统中一个或多个实际文件&#xff1b;而对于每个独立表空间来说&#xff0c;对应着文件系统中一个名为表名.ibd 的实际文件。可以把表空间想象成由很多个页组成的池子&…

【Unity 实用工具篇】| 游戏多语言解决方案,官方插件Localization 实现本地化及多种语言切换

前言 【Unity 实用工具篇】| 游戏多语言解决方案&#xff0c;官方插件Localization 实现本地化及多种语言切换一、多语言本地化插件 Localization1.1 介绍1.2 效果展示1.3 使用说明 二、 插件导入并配置2.1 安装 Localization2.2 全局配置 三、多语言映射表3.1 创建多语言文本配…

字符处理 C语言xdoj52

问题描述 从键盘输入一个字符&#xff0c;若为小写字母&#xff0c;则输出其对应的大写字母&#xff1b;若为大写字母&#xff0c;则输出对应的小写字母&#xff1b;其他字符原样输出。 输入说明 输入一个字符 输出说明 输出一个字符 输入样例 样例1输入 a 样例…

分布式块存储 ZBS 的自主研发之旅|元数据管理

重点内容 元数据管理十分重要&#xff0c;犹如整个存储系统的“大黄页”&#xff0c;如果元数据操作出现性能瓶颈&#xff0c;将严重影响存储系统的整体性能。如何提升元数据处理速度与高可用是元数据管理的挑战之一。SmartX 分布式存储 ZBS 采用 Log Replication 的机制&…

论文修改润色平台 PaperBERT

大家好&#xff0c;今天来聊聊论文修改润色平台&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; 标题&#xff1a;论文修改润色平台――助力学术研究&#xff0c;提升论文质量 一、引言 在学术研究中&am…

复制粘贴——QT实现原理

复制粘贴——QT实现原理 QT 剪贴板相关类 QClipboard 对外通用的剪贴板类&#xff0c;一般通过QGuiApplication::clipboard() 来获取对应的剪贴板实例。 // qtbase/src/gui/kernel/qclipboard.h class Q_GUI_EXPORT QClipboard : public QObject {Q_OBJECT private:explici…

单片机——通信协议(FPGA+c语言应用之spi协议解析篇)

引言 串行外设接口(SPI)是微控制器和外围IC&#xff08;如传感器、ADC、DAC、移位寄存器、SRAM等&#xff09;之间使用最广泛的接口之一。本文先简要说明SPI接口&#xff0c;然后介绍ADI公司支持SPI的模拟开关与多路转换器&#xff0c;以及它们如何帮助减少系统电路板设计中的数…

ChatGLM大模型推理加速之Speculative Decoding

目录 一、推测解码speculative decoding 1、自回归解码 2、speculative decoding 3、细节理解 二、核心逻辑代码 1、算法流程代码 2、模型自回归代码 a、带缓存的模型自回归实现代码 b、优化版本带缓存的模型自回归实现代码 c、ChatGLM的past_key_values的回滚 三、…