LeetCode 105.从前序与中序遍历序列构造二叉树

LeetCode 105.从前序与中序遍历序列构造二叉树

1、题目

题目链接:105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:
image.png

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder 和 inorder 均 无重复 元素
  • inorder 均出现在 preorder
  • preorder 保证 为二叉树的前序遍历序列
  • inorder 保证 为二叉树的中序遍历序列

2、递归

思路

二叉树前序遍历的顺序为:
先遍历根节点;
随后递归地遍历左子树;
最后递归地遍历右子树。
二叉树中序遍历的顺序为:
先递归地遍历左子树;
随后遍历根节点;
最后递归地遍历右子树。
在「递归」地遍历某个子树的过程中,我们也是将这颗子树看成一颗全新的树,按照上述的顺序进行遍历。挖掘「前序遍历」和「中序遍历」的性质,我们就可以得出本题的做法。

代码

class Solution {
private:unordered_map<int, int> index;public:TreeNode* myBuildTree(const vector<int>& preorder, const vector<int>& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {if (preorder_left > preorder_right) {return nullptr;}// 前序遍历中的第一个节点就是根节点int preorder_root = preorder_left;// 在中序遍历中定位根节点int inorder_root = index[preorder[preorder_root]];// 先把根节点建立出来TreeNode* root = new TreeNode(preorder[preorder_root]);// 得到左子树中的节点数目int size_left_subtree = inorder_root - inorder_left;// 递归地构造左子树,并连接到根节点// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素root->left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);// 递归地构造右子树,并连接到根节点// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素root->right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {int n = preorder.size();// 构造哈希映射,帮助我们快速定位根节点for (int i = 0; i < n; ++i) {index[inorder[i]] = i;}return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);}
};

复杂度分析

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

3、递归(带日志)

思路

带日志的版本C++代码如下: (带日志的版本仅用于调试,不要在leetcode上提交,会超时

代码

class Solution {
private:TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& preorder, int preorderBegin, int preorderEnd) {if (preorderBegin == preorderEnd) return NULL;int rootValue = preorder[preorderBegin]; // 注意用preorderBegin 不要用0TreeNode* root = new TreeNode(rootValue);if (preorderEnd - preorderBegin == 1) return root;int delimiterIndex;for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break;}// 切割中序数组// 中序左区间,左闭右开[leftInorderBegin, leftInorderEnd)int leftInorderBegin = inorderBegin;int leftInorderEnd = delimiterIndex;// 中序右区间,左闭右开[rightInorderBegin, rightInorderEnd)int rightInorderBegin = delimiterIndex + 1;int rightInorderEnd = inorderEnd;// 切割前序数组// 前序左区间,左闭右开[leftPreorderBegin, leftPreorderEnd)int leftPreorderBegin =  preorderBegin + 1;int leftPreorderEnd = preorderBegin + 1 + delimiterIndex - inorderBegin; // 终止位置是起始位置加上中序左区间的大小size// 前序右区间, 左闭右开[rightPreorderBegin, rightPreorderEnd)int rightPreorderBegin = preorderBegin + 1 + (delimiterIndex - inorderBegin);int rightPreorderEnd = preorderEnd;cout << "----------" << endl;cout << "leftInorder :";for (int i = leftInorderBegin; i < leftInorderEnd; i++) {cout << inorder[i] << " ";}cout << endl;cout << "rightInorder :";for (int i = rightInorderBegin; i < rightInorderEnd; i++) {cout << inorder[i] << " ";}cout << endl;cout << "leftPreorder :";for (int i = leftPreorderBegin; i < leftPreorderEnd; i++) {cout << preorder[i] << " ";}cout << endl;cout << "rightPreorder :";for (int i = rightPreorderBegin; i < rightPreorderEnd; i++) {cout << preorder[i] << " ";}cout << endl;root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  preorder, leftPreorderBegin, leftPreorderEnd);root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, preorder, rightPreorderBegin, rightPreorderEnd);return root;}public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if (inorder.size() == 0 || preorder.size() == 0) return NULL;return traversal(inorder, 0, inorder.size(), preorder, 0, preorder.size());}
};

复杂度分析

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

4、递归

思路

代码

class Solution {
private:TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& preorder, int preorderBegin, int preorderEnd) {if (preorderBegin == preorderEnd) return NULL;int rootValue = preorder[preorderBegin]; // 注意用preorderBegin 不要用0TreeNode* root = new TreeNode(rootValue);if (preorderEnd - preorderBegin == 1) return root;int delimiterIndex;for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break;}// 切割中序数组// 中序左区间,左闭右开[leftInorderBegin, leftInorderEnd)int leftInorderBegin = inorderBegin;int leftInorderEnd = delimiterIndex;// 中序右区间,左闭右开[rightInorderBegin, rightInorderEnd)int rightInorderBegin = delimiterIndex + 1;int rightInorderEnd = inorderEnd;// 切割前序数组// 前序左区间,左闭右开[leftPreorderBegin, leftPreorderEnd)int leftPreorderBegin =  preorderBegin + 1;int leftPreorderEnd = preorderBegin + 1 + delimiterIndex - inorderBegin; // 终止位置是起始位置加上中序左区间的大小size// 前序右区间, 左闭右开[rightPreorderBegin, rightPreorderEnd)int rightPreorderBegin = preorderBegin + 1 + (delimiterIndex - inorderBegin);int rightPreorderEnd = preorderEnd;root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  preorder, leftPreorderBegin, leftPreorderEnd);root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, preorder, rightPreorderBegin, rightPreorderEnd);return root;}public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if (inorder.size() == 0 || preorder.size() == 0) return NULL;// 参数坚持左闭右开的原则return traversal(inorder, 0, inorder.size(), preorder, 0, preorder.size());}
};

复杂度分析

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

5、迭代

思路

代码

class Solution {
public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if (!preorder.size()) {return nullptr;}TreeNode* root = new TreeNode(preorder[0]);stack<TreeNode*> stk;stk.push(root);int inorderIndex = 0;for (int i = 1; i < preorder.size(); ++i) {int preorderVal = preorder[i];TreeNode* node = stk.top();// 如果栈顶节点的值不等于中序遍历的当前值if (node->val != inorder[inorderIndex]) {// 则当前节点是栈顶节点的左子节点node->left = new TreeNode(preorderVal);// 将左子节点压入栈中stk.push(node->left);}else {// 否则,不断弹出栈顶节点,直到栈顶节点的值不等于中序遍历的当前值while (!stk.empty() && stk.top()->val == inorder[inorderIndex]) {node = stk.top();stk.pop();++inorderIndex;}// 当前节点是栈顶节点的右子节点node->right = new TreeNode(preorderVal);// 将右子节点压入栈中stk.push(node->right);}}return root;}
};

复杂度分析

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

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

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

相关文章

MVCC 详解

介绍 MVCC&#xff0c;全称 Multi-Version Concurrency Control&#xff0c;即多版本并发控制 MVCC的目的主要是为了提高数据库并发性能&#xff0c;用更好的方式去处理读-写冲突&#xff0c;做到即使有读写冲突时&#xff0c;也能做到不加锁。 这里的多版本指的是数据库中同时…

【GO】go语言中的HTTP标准库 - http编程

上一节已经学习了HTTP的基础知识&#xff0c;本章将学习关于go语言的HTTP编程&#xff0c;最重要的是掌握 net/http 包的用法&#xff0c;以及如何自己编写一个简单的Web服务端&#xff0c;通过客户端访问Server端等。 编写简单的Web 服务器 http.ListenAndServe 启动 Http S…

Unity开发中导弹路径散射的原理与实现

Unity开发中导弹路径散射的原理与实现 前言逻辑原理代码实现导弹自身脚本外部控制脚本 应用效果结语 前言 前面我们学习了导弹的追踪的效果&#xff0c;但是在动画或游戏中&#xff0c;我们经常可以看到导弹发射后的弹道是不规则的&#xff0c;扭扭曲曲的飞行&#xff0c;然后击…

Reactor Netty 其他-响应式编程-018

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Nex…

vue3点击添加小狗图片,vue3拆分脚本

我悄悄蒙上你的眼睛 模板和样式 <template><div class"XueXi_Hooks"><img v-for"(dog, index) in dog1List" :src"dog" :key"index" /><button click"addDog1">点我添加狗1</button><hr …

每日一题9:Pandas-填充缺失值

一、每日一题 DataFrame products --------------------- | Column Name | Type | --------------------- | name | object | | quantity | int | | price | int | ---------------------编写一个解决方案&#xff0c;在 quantity 列中将缺失的值 编…

Leetcode 剑指 Offer II 077.排序链表

题目难度: 中等 原题链接 今天继续更新 Leetcode 的剑指 Offer&#xff08;专项突击版&#xff09;系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~ 题目描述 给定链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排…

Xilinx 千兆以太网TEMAC IP核 MDIO 配置及物理接口

基于AXI4-Lite接口可以访问MDIO(Management Data Input/Output)接口&#xff0c;而MDIO接口连接MAC外部的PHY芯片&#xff0c;用户可通过AXI4-Lite接口实现对PHY芯片的配置。 1 MDIO接口简介 开放系统互连模型OSI的最低两层分别是数据链路层和物理层&#xff0c;数据链路层的…

音视频入门基础:像素格式专题(2)——不通过第三方库将RGB24格式视频转换为BMP格式图片

音视频入门基础&#xff1a;像素格式专题系列文章&#xff1a; 音视频入门基础&#xff1a;像素格式专题&#xff08;1&#xff09;——RGB简介 音视频入门基础&#xff1a;像素格式专题&#xff08;2&#xff09;——不通过第三方库将RGB24格式视频转换为BMP格式图片 一、引…

xilinx xdma drive 传输8MB以上数据受限的问题

当传输超过8 MB数据时报错error code1359&#xff0c; #define XDMA_MAX_TRANSFER_SIZE (8UL * 1024UL * 1024UL) 可以修改成&#xff1a; #define XDMA_MAX_TRANSFER_SIZE (80UL * 1024UL * 1024UL) VS2019 WDK环境的搭建 先准备好VS WDK的驱动开发环境。需要下载VS、SD…

5 个遥遥领先的大模型 RAG 工具

想象一下拥有一种超能力&#xff0c;让你能够对任何问题或提示生成类似人类的回答&#xff0c;同时还能够利用庞大的外部知识库确保准确性和相关性。这不是科幻小说&#xff0c;这就是检索增强生成&#xff08;RAG&#xff09;的力量。 在本文中&#xff0c;我们将介绍五大遥遥…

NASA数据集——2002-2011年全球18.7 至 89.0 千兆赫的亮度温度、海冰浓度和海冰积雪深度三级网格产品(AE_SI12)数据

AMSR-E/Aqua Daily L3 12.5 km Brightness Temperature, Sea Ice Concentration, & Snow Depth Polar Grids V003 三级网格产品&#xff08;AE_SI12&#xff09;包括 18.7 至 89.0 千兆赫的亮度温度、海冰浓度和海冰积雪深度。 简介 美国国家航空航天局地球观测系统 Aqu…

几个Python处理Excel实际应用

下面介绍四个不同类型的Python处理Excel的经典应用案例&#xff0c;以帮助读者更好地掌握Python处理Excel的技能。 一、读取Excel数据 Python通过pandas库可以轻松地读取Excel数据。pandas库是一个专门用于数据分析和处理的库&#xff0c;它可以将Excel中的数据读取为DataFra…

HIVE调优MapJoin

HIVE调优MapJoin 目录 HIVE调优MapJoin 1.mapjoin &#xff08;1.2以后自动默认启动mapjoin&#xff09; 2.创建表格 3.查询建表 4.通过 explain 展示执行计划 5.Map JOIN 相关设置&#xff1a; 1.mapjoin &#xff08;1.2以后自动默认启动mapjoin&#xff09;…

08.3.grafana自定义图形

grafana自定义图形 找插件里面的zabbix 点击update 数据源—zabbix数据源,添加zabbix数据源 选择zabbix类型 我这里配置的是本地&#xff0c;所以URL直接localhost 这里配置zabbix登录账号密码Admin/zabbix 然后点击保存并测试&#xff0c;会直接显示版本 导入模板&…

2024年数维杯数学建模

高质量原创论文已完成 需要的私我

【软考高项】四十四、高级项目管理

一、项目集管理 相关角色 项目集发起人、项目集指导委员会、项目集经理、其他影响项目集的干系人项目集管理绩效域 项目集战略一致性、项目集效益管理、项目集干系人参与、项目集治理和项目集生命周期管理 二、项目组合管理 项目组合经理角色 项目组合管理原…

【深度学习】Diffusion扩散模型的逆扩散问题

1、前言 上一篇&#xff0c;我们讲了Diffusion这个模型的原理推导。但在推导中&#xff0c;仍然遗留了一些问题。本文将解决那些问题 参考论文&#xff1a; ①Variational Diffusion Models (arxiv.org) ②Tutorial on Diffusion Models for Imaging and Vision (arxiv.org…

Mysql数据库的基础学习

为什么使用数据库&#xff1f; 1.持久化&#xff1a;将数据保存到可掉电式存储设备中以供使用。 数据库相关概念&#xff1a; DB:数据库&#xff08;Databass&#xff09;即存储数据的仓库&#xff0c;本质是一个文件系统&#xff0c;保存了一系列有组织的数据DBMS:数据库管…

PyCharm2024安装教程

PyCharm是一款功能强大的Python集成开发环境&#xff08;IDE&#xff09;&#xff0c;它提供了许多工具和功能来帮助开发者编写、调试和测试Python代码。以下是使用PyCharm的基本步骤&#xff1a; 安装PyCharm&#xff1a;首先&#xff0c;你需要从JetBrains官方网站下载并安装…