重建二叉树(C++)
目录
1 问题描述
1.1 示例1
1.2 示例2
1.3 示例3
2 解题思路
3 代码实现
4 代码解析
4.1 初始化
4.2 递归部分
4.3 主逻辑
5 总结
1 问题描述
给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

提示:
1.vin.length == pre.length
2.pre 和 vin 均无重复元素
3.vin出现的元素均出现在 pre里
4.只需要返回根结点,系统会自动输出整颗树做答案对比
数据范围:n≤2000n≤2000,节点的值 −10000≤val≤10000−10000≤val≤10000
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
1.1 示例1
输入:
[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]
返回值:
{1,2,3,4,#,5,6,#,7,#,#,8}
1.2 示例2
输入:
[1],[1]
返回值:
{1}
1.3 示例3
输入:
[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值:
{1,2,5,3,4,6,7}
2 解题思路
首先,我们通过中序遍历构建一个哈希表,将每个节点值与其在中序遍历中的索引进行映射,这样可以在构建树时快速定位每个节点的左右子树范围。然后,利用递归的方式构建树。在递归过程中,前序遍历的第一个元素为当前子树的根节点,根据根节点在中序遍历中的位置可以划分左右子树的范围。每次递归调用时,分别构建左右子树,直到树的叶子节点(即子树为空)为止。最终,递归返回构建好的二叉树。
3 代码实现
/*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* };*/
#include <unordered_map>
#include <vector>
class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param preOrder int整型vector* @param vinOrder int整型vector* @return TreeNode类*/unordered_map<int, int> indexMap;TreeNode* buildTree(vector<int>& preOrder, int preStart, int preEnd, vector<int>& vinOrder, int inStrat, int inEnd) {if (preStart > preEnd) return nullptr;int rootVal = preOrder[preStart];TreeNode* root = new TreeNode(rootVal);int rootIndex = indexMap[rootVal];int leftSize = rootIndex - inStrat;root->left = buildTree(preOrder, preStart + 1, preStart + leftSize, vinOrder, inStrat, rootIndex - 1);root->right = buildTree(preOrder, preStart + leftSize + 1, preEnd, vinOrder, rootIndex + 1, inEnd);return root;}TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {// write code hereint n = preOrder.size();for (int i = 0; i < n; i++){indexMap[vinOrder[i]] = i;}return buildTree(preOrder, 0, n - 1, vinOrder, 0, n - 1);}
};
4 代码解析
4.1 初始化
unordered_map<int, int> indexMap;
首先定义了一个 unordered_map<int, int> 类型的 indexMap,该映射用来存储中序遍历数组中每个节点值的索引位置。这种做法能够在递归过程中快速查找某个节点在中序遍历中的位置,避免了每次都遍历中序数组,从而提高了算法的效率。
4.2 递归部分
TreeNode* buildTree(vector<int>& preOrder, int preStart, int preEnd, vector<int>& vinOrder, int inStrat, int inEnd) {if (preStart > preEnd) return nullptr;int rootVal = preOrder[preStart];TreeNode* root = new TreeNode(rootVal);int rootIndex = indexMap[rootVal];int leftSize = rootIndex - inStrat;root->left = buildTree(preOrder, preStart + 1, preStart + leftSize, vinOrder, inStrat, rootIndex - 1);root->right = buildTree(preOrder, preStart + leftSize + 1, preEnd, vinOrder, rootIndex + 1, inEnd);return root;
}
在 buildTree 函数中,递归的基础条件是 preStart > preEnd,此时表示当前子树没有节点,返回 nullptr。通过前序遍历数组的 preStart 位置来获取根节点的值 rootVal。接着,利用 indexMap 快速查找该根节点在中序遍历中的位置 rootIndex,并根据该位置确定左子树的大小 leftSize。然后递归构建左子树和右子树,分别处理前序和中序遍历数组中的相应部分,最后返回当前根节点。
4.3 主逻辑
TreeNode* reConstructBinaryTree(vector<int>& preOrder, vector<int>& vinOrder) {int n = preOrder.size();for (int i = 0; i < n; i++) {indexMap[vinOrder[i]] = i;}return buildTree(preOrder, 0, n - 1, vinOrder, 0, n - 1);
}
在 reConstructBinaryTree 函数中,首先通过一个循环填充 indexMap,它记录了中序遍历中每个节点值的索引。这一步为后续的递归过程提供了高效的查找支持。然后,调用 buildTree 函数开始递归构建二叉树,传入前序遍历和中序遍历的整个范围,最终返回构建完成的二叉树的根节点。
5 总结
该算法使用前序遍历和中序遍历的特点,通过递归重建二叉树。在每一步中,通过根节点在中序遍历中的位置来划分左子树和右子树,避免了不必要的遍历。unordered_map 提供了 O(1) 时间复杂度的查找功能,使得整体算法在时间和空间上的效率都得到了保证。整个算法的时间复杂度为 O(n),空间复杂度为 O(n),其中 n 是二叉树的节点数量。
相关文章:
重建二叉树(C++)
目录 1 问题描述 1.1 示例1 1.2 示例2 1.3 示例3 2 解题思路 3 代码实现 4 代码解析 4.1 初始化 4.2 递归部分 4.3 主逻辑 5 总结 1 问题描述 给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。 例如输入前序遍历序…...
VLAN、QinQ、VXLAN的区别
1、技术本质与封装方式 技术OSI层级封装原理标识位长度拓展性VLAN数据链路层L2在以太网帧头插入802.1Q Tag(单层VLAN标签)12位(4094个)有限,仅支持单一网络域内隔离QinQ数据链路层L2在原始VLAN标签外再封装一层802.1Q…...
保姆级教程:synchronized 同步方法 vs 同步代码块,看完彻底懂锁!
一、同步方法(锁住整个方法) 1. 代码示例 public class Counter {private int count 0;// 同步方法:锁住整个方法public synchronized void add() {count;}// 同步方法:锁住整个方法public synchronized void subtract() {coun…...
10乱码问题的解释(1)
在计算机中,一个汉字,占几个字节? 针对这个问题,只要你回答出一个具体的数字,就一定是错的!! 前提条件: 当前中文编码使用的是哪种方式(字符集) 计算机存的其实是二进制数字~~ 英文字母,怎么表示的?? ASCII 码表~~ 规定了每个字符,都有一个对应的数字来表示~~ 只是表示英文,…...
短视频文案--钓鱼女和滑板女
短视频文案 第一个文案: 1标题:风萧萧兮易水寒,美女钓鱼兮不复还 2内容: 我站在池边的微风中,再也看不到曾经快乐的少女了。 风很凉,凉得心不知前往何处。 水很清,清得深知这里没鱼群。 芦苇…...
算法设计学习3
实验目的及要求: 1.加强对结构体的应用。 2.熟悉字符计数排序。 实验设备环境: 1.微型计算机 2.DEV C(或其他编译软件) 实验步骤: 任务:要求使用自定义函数来实现 输入一段文本,统计每个字符出现的次数,按…...
nginx的自动跳转https
mkdir /usr/local/nginx/certs/ 创建一个目录 然后用openssl生成证书 编辑nginx的配置文件 自动跳转成功 做一个优化,如果访问的时候后面加了其他的uri也一起自动跳转了...
python-leetcode 62.搜索插入位置
题目: 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置 方法一:二分查找 假设题意是在排序数组中寻找是否存在一个目标值,则可以…...
2. ollama下载及安装deepseek模型
ollamam 1. ollama2. ollama常用命令3. Windows配置Ollama与DeepSeek自定义目录环境3.1 自定义安装3.3 添加到系统变量 1. ollama 官网地址 下载地址 测试安装 deepseek模型下载地址 根据电脑性能下载对应版本 2. ollama常用命令 # 运行模型 ollama run 模型 # 查看模型…...
deepseek使用记录26——思维混乱背后的理论泡沫与骗局
一 后现代主义哲学自20世纪60年代兴起以来,其理论形态和社会影响一直备受争议。支持者认为它是对现代性弊病的批判和解构,而反对者则将其视为一种脱离现实的“工业化学术生产”,甚至是一场哲学骗局。结合相关文献和案例,可从以下角…...
服务器入门操作1(深度学习)
服务器相关 基本命令 查看GPU状态: 查看GPU信息查看CPU信息查看系统版本号 nvidia-smi lscpu lsb_release -a清屏: clearanaconda相关: 查看环境列表激活虚拟环境退出虚拟环境跳转至目录跳转至上一级目录 conda env list conda activa…...
Qt基本框架(1)
本篇主要介绍Qt的基本框架,并实现简单的按钮事件 本文部分ppt、视频截图原链接:[萌马工作室的个人空间-萌马工作室个人主页-哔哩哔哩视频] 1. Qt基本框架介绍 Qt基本框架主要分为两部分:Qt实例对象和Qt窗口。Qt实例对象负责初始化Qt运行时…...
Buzz1.2.0视频语音转成TXT、SRT、VTT工具
buzz0.9.0.exe下载 https://download.csdn.net/download/u011000529/90551347 特征 导入音频和视频文件并导出文本到 TXT、SRT 和 VTT从您计算机的麦克风转录和翻译成文本(资源密集型且可能不是实时的,Demo)支持Whisper、 Whisper.cpp、Fast…...
动手学深度学习:AlexNet
前言 从这个模型开始,我的数据集主阵地就将从装甲板转移到手语视频数据集,模型开始变得更加复杂,数据集当然也要更复杂啦,我将记录在这个过程中遇到的问题和解决后续。 数据读取 由于是视频数据集,我采取的方法是将…...
MySql之binlog与数据恢复(Binlog and Data Recovery in MySQL)
MySql之binlog与数据恢复 什么是binlog binlog我们一般叫做归档日志,他是mysql服务器层的日志,跟存储引擎无关,他记录的是所有DDL和DML的语句,不包含查询语句,binlog是一种逻辑日志,他记录的是sql语句的原…...
JDK1.8和Maven、Git安装教程自用成功
一.JDK安装 JRK:java运行环境 JDK:java语言的软件开发工具包;JDK里包含了java开发工具,也包含了JRE 1.下载JDK1.8并安装 Java Downloads | Oracle 进入官网后往下翻,找到JAVA8; 然后选择对应的版本&am…...
数据采集助力AI大模型训练
引言使用抓取浏览器采集ebay商品页面选购亮数据AI训练数据总结 引言 AI技术在今天已经是我们工作生活中不可或缺的工具,很多小伙伴也在致力于训练AI模型。高质量的数据是训练强大AI模型的核心驱动力,无论是自然语言处理、计算机视觉还是推荐系统…...
WPF中viewmodel单例模式
1、单例模式介绍 单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。它常用于需要全局唯一访问点的场景,如配置管理、日志记录、数据库连接等。 2、WPF 中 ViewModel 的单例实现 在 WPF 中&#…...
Rust 为什么不适合开发 GUI
前言 在当今科技蓬勃发展的时代,Rust 编程语言正崭露头角,逐步为世界上诸多重要基础设施提供动力支持。从存储海量信息到应用于 Linux 内核,Rust 展现出强大的实力。然而,当涉及构建 GUI(图形用户界面)时&…...
消息队列篇--通信协议篇--理解HTTP、TLS和TCP如何协同工作
前面介绍了HTTP/HTTPS,SSL/TLS以及TCP和UDP,这些在网络传输上分别有着自己的作用。为了深入理解下这些概念,本篇重点介绍下HTTP、TLS 和 TCP是如何协同工作的?我们从底层到上层逐步分析每个协议的作用及其相互关系。这些协议共同协…...
代码随想录算法训练营第三十四天 | 62.不同路径 63.不同路径II 343.整数拆分
62.不同路径 题目链接:62. 不同路径 - 力扣(LeetCode) 文章讲解:代码随想录 视频讲解:动态规划中如何初始化很重要!| LeetCode:62.不同路径_哔哩哔哩_bilibili 思路:机器人位于一…...
2023第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(真题题解)(C++/Java题解)
记录刷题的过程、感悟、题解。 希望能帮到,那些与我一同前行的,来自远方的朋友😉 大纲: 1、日期统计-(解析)-暴力dfs(😉蓝桥专属 2、01串的熵-(解析)-不要chu…...
RK3568-适配ov5647摄像头
硬件原理图 CAM_GPIO是摄像头电源控制引脚,连接芯片GPIO4_C2 CAM_LEDON是摄像头led灯控制引脚,连接芯片GPIO4_C3编写设备树 / {ext_cam_clk: external-camera-clock {compatible = "fixed-clock";clock-frequency = <25000000>;clock-output-names = "…...
Java的设计模式详解
摘要:设计模式是软件工程中解决常见问题的经典方案。本文结合Java语言特性,深入解析常用设计模式的核心思想、实现方式及实际应用场景,帮助开发者提升代码质量和可维护性。 一、设计模式概述 1.1 什么是设计模式? 设计模式&…...
实战篇Redis
黑马程序员的Redis的笔记(后面补一下图片) 【黑马程序员Redis入门到实战教程,深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目】https://www.bilibili.com/video/BV1cr4y1671t?p72&vd_source001f1c33a895eb5ed820b9a4…...
化学方程式配平 第33次CCF-CSP计算机软件能力认证
很经典的大模拟题目 但是还不算难 大模拟题最需要注意的就是细节 写代码一定要考虑全面 并且要细心多debug 多打断点STL库的熟练使用 istringstream真的处理字符串非常好用 注意解耦合思想 这样改代码debug更加清晰 https://www.acwing.com/problem/content/5724/ #includ…...
Java基础-25-继承-方法重写-子类构造器的特点-构造器this的调用
在面向对象编程中,继承是实现代码复用和扩展的重要机制。通过继承,子类可以继承父类的属性和方法,并且可以通过方法重写来改变或扩展父类的行为。此外,构造器在对象初始化过程中扮演了重要角色,尤其是在子类构造器中如…...
nvidia 各 GPU 架构匹配的 CUDA arch 和 CUDA gencode
使用 NVCC 进行编译 cuda c(.cu)时,arch 标志 (-arch) 指定了 CUDA 文件将为其编译的 NVIDIA GPU 架构的名称。 Gencodes (-gencode) 允许更多的 PTX 代,并且可以针对不同的架构重复多次。 NVIDIA 架构名称的列表,以及它们具有的计算能力&am…...
沉浸式体验测评|AI Ville:我在Web3小镇“生活”了一周
最近,我在朋友的推荐下,体验了 aivillebot 的项目。起初,我只是抱着试试看的心态,心想这不就是个 Web3 版的《星露谷物语》吗? 但是一周下来,我发现这个虚拟小镇也没那么简单——里面的居民不是目前端游或链…...
TTL 值 | 在 IP 协议、ping 工具及 DNS 解析中的作用
注:本文为 “TTL” 相关文章合辑。 未整理去重。 如有内容异常,请看原文。 TTL 值的意义 2007-10-18 11:33:17 TTL 是 IP 协议包中的一个值,用于标识网络路由器是否应丢弃在网络中停留时间过长的数据包。数据包可能因多种原因在一定时间内…...
