【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树

文章目录

  • 一、题目
  • 二、解法
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、题目

在这里插入图片描述

二、解法

  思路分析:首先我们要知道后序遍历数组的最后一个元素必然是根节点,然后根据根节点在中序遍历数组中的位置进行划分,得到根节点的左右子树遍历数组,以此递归。当然这里有一个前提,遍历数组的元素不得重复,否则构造的二叉树不唯一。因此我们根据根节点的值找到中序遍历数组中的根节点索引,以此划分出左右区间,然后进行递归。
  程序如下

class Solution {
public:TreeNode* traversal(const vector<int>& inorder, int inorderBegin, int inorderEnd, const vector<int>& postorder, int postorderBegin, int postorderEnd) { // 1、判断是否为空数组,直接返回if (inorderBegin == inorderEnd || postorderBegin == postorderEnd) return NULL;// 2、后序遍历数组最后一个元素,就是当前的中间节点int rootValue = postorder[postorderEnd - 1];    TreeNode* root = new TreeNode(rootValue);// 3、叶子节点,后序数组只剩下一个元素,树构造完毕,返回if (postorderBegin - postorderEnd == 1) return root;// 4、找切割点int delimiterIndex;for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break; // 这里注意二叉树遍历数组的值不能重复,否则二叉树不唯一,这里默认是唯一二叉树,值不重复。}// 5、切割中序数组,得到 中序左数组和中序右数组int leftinorderBegin = inorderBegin;int leftinorderEnd = delimiterIndex;int rightinorderBegin = delimiterIndex + 1;int rightinorderEnd = inorder.size();// 6、切割后序数组,得到 后序左数组和后序右数组int leftpostorderBegin = postorderBegin;int leftpostorderEnd = postorderBegin + delimiterIndex - inorderBegin;// 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了// 7、递归root->left = traversal(inorder, leftinorderBegin, leftinorderEnd, postorder, leftpostorderBegin, leftpostorderEnd);root->right = traversal(inorder, rightinorderBegin, rightinorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {       return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());}
};

三、完整代码

# include <iostream>
# include <vector>
# include <queue>
# include <string>
# include <algorithm>
# include <stack>
using namespace std;// 树节点定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode() : val(0), left(nullptr), right(nullptr) {}TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};class Solution {
public:TreeNode* traversal(const vector<int>& inorder, int inorderBegin, int inorderEnd, const vector<int>& postorder, int postorderBegin, int postorderEnd) { // 1、判断是否为空数组,直接返回if (inorderBegin == inorderEnd || postorderBegin == postorderEnd) return NULL;// 2、后序遍历数组最后一个元素,就是当前的中间节点int rootValue = postorder[postorderEnd - 1];    TreeNode* root = new TreeNode(rootValue);// 3、叶子节点,后序数组只剩下一个元素,树构造完毕,返回if (postorderBegin - postorderEnd == 1) return root;// 4、找切割点int delimiterIndex;for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {if (inorder[delimiterIndex] == rootValue) break; // 这里注意二叉树遍历数组的值不能重复,否则二叉树不唯一,这里默认是唯一二叉树,值不重复。}// 5、切割中序数组,得到 中序左数组和中序右数组int leftinorderBegin = inorderBegin;int leftinorderEnd = delimiterIndex;int rightinorderBegin = delimiterIndex + 1;int rightinorderEnd = inorder.size();// 6、切割后序数组,得到 后序左数组和后序右数组int leftpostorderBegin = postorderBegin;int leftpostorderEnd = postorderBegin + delimiterIndex - inorderBegin;// 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了// 7、递归root->left = traversal(inorder, leftinorderBegin, leftinorderEnd, postorder, leftpostorderBegin, leftpostorderEnd);root->right = traversal(inorder, rightinorderBegin, rightinorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {       return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());}
};template<class T1, class T2>
void my_print2(T1& v, const string str) {cout << str << endl;for (class T1::iterator vit = v.begin(); vit < v.end(); ++vit) {for (class T2::iterator it = (*vit).begin(); it < (*vit).end(); ++it) {cout << *it << ' ';}cout << endl;}
}// 层序遍历
vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> que;if (root != NULL) que.push(root);vector<vector<int>> result;while (!que.empty()) {int size = que.size();  // size必须固定, que.size()是不断变化的vector<int> vec;for (int i = 0; i < size; ++i) {TreeNode* node = que.front();que.pop();vec.push_back(node->val);if (node->left) que.push(node->left);if (node->right) que.push(node->right);}result.push_back(vec);}return result;
}int main()
{//vector<int> inorder = {9, 3, 15, 20, 7};//vector<int> postorder = { 9, 15, 7, 20, 3 };vector<int> inorder = { 1, 2, 3};vector<int> postorder = { 3, 2, 1};Solution s;TreeNode* root = s.buildTree(inorder, postorder);vector<vector<int>> tree = levelOrder(root);my_print2<vector<vector<int>>, vector<int>>(tree, "目标树:");system("pause");return 0;
}

end

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

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

相关文章

postgres源码解析55 Brin Index--2(brinbuild流程)

上一篇讲解了brin index的基本概念以及页布局postgres源码解析54 Brin Index–1&#xff0c;后续会从源码角度对索引的构建、维护等方面进行深入讲解。 1 关键数据结构 2 brinbuild执行流程图 3 brinbuild 函数详解 1 首先调用brin_matepage_init初始化brin meta元数据页&…

【0904作业】QT 完成登陆界面跳转到聊天室+完成学生管理系统的查找和删除功能

一、完成登陆界面跳转到聊天室 1> 项目结构 2> 源码 ① .pro ②main #include "mywnd.h" #include"chatCli.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MyWnd w;w.show();Form f;QObject::co…

Lite transformer

图片以及思想来源请参考论文 Lite Transformer with Long-Short Range Attention 瓶颈结构&#xff08;bottleneck&#xff09;是否真的有效 注意力机制被广泛应用在诸多领域&#xff0c;包括自然语言处理&#xff0c;图像处理和视频处理。它通过计算所有输入元素的点积来建模…

低代码平台:IVX 重新定义编程

目录 &#x1f36c;一、写在前面 &#x1f36c;二、低代码平台是什么 &#x1f36c;三、为什么程序员和技术管理者不太可能接受“低代码”平台&#xff1f; &#x1f36d;1、不安全&#xff08;锁定特性&#xff09; &#x1f36d;2、不信任 &#x1f36c;四、IVX低代码平台 &a…

《阿里巴巴 Java 开发手册》(一)命名风格

《阿里巴巴 Java 开发手册》 一、编程规约(一)命名风格(二)常量定义(三)代码格式 一、编程规约 (一)命名风格 (二)常量定义 (三)代码格式

LabVIEW开发感应电机在线匝间短路故障诊断系统

LabVIEW开发感应电机在线匝间短路故障诊断系统 工业中使用的超过85%的电动机是三相感应电动机。它们因其可靠性、设计便利性、高性能和过载能力而被广泛用于不同的应用&#xff0c;例如制造、加工、电力系统、运输等。无论它们的能力如何&#xff0c;它们都被认为是现代工业学…

Unity通过偏移UV播放序列帧动画

大家好&#xff0c;我是阿赵。   在Unity引擎里面用shader播放序列图&#xff0c;估计很多人都有用到了&#xff0c;我自己而已写过好几个版本。这里大概介绍一下。 一、原理 先说目的&#xff0c;我现在有一张这样的图片&#xff1a; 这张图片上面&#xff0c;有9个格子&a…

使用errors.Wrapf()代替log.Error()

介绍不同语言的错误处理机制: Error handling patterns[1] Musings about error handling mechanisms in programming languages[2] 项目中 main调func1&#xff0c;func1调取func2... 这样就会出现很多的 if err ! nil { log.Printf()} , 在Kibana上查看时会搜到多条日志, 需要…

美妆+七人拼团模式:如何打造新型社交电商营销方式

美妆是一个充满竞争和创新的行业&#xff0c;要想在市场上获得优势&#xff0c;就需要不断寻找新的营销方式&#xff0c;吸引和留住消费者。七人拼团模式就是一种结合了社交电商和拼购玩法的新型商业模式&#xff0c;它可以利用社交网络的裂变效应&#xff0c;增加品牌曝光度和…

vue+elementUI el-select 自定义搜索逻辑(filter-method)

下拉列表的默认搜索是搜索label显示label,我司要求输入id显示label名称 <el-form-item label"部门&#xff1a;"><el-select v-model"form.region1" placeholder"请选择部门" filterable clearable:filter-method"dataFilter&qu…

AndroidTV端:酒店扫码认证投屏DLNA

被老板叼了几次了&#xff0c;最近实在忍不了&#xff0c;准备离职&#xff1b; 但是担心离职后长时间没有办法找到工作 就想贡献一套平时琢磨出来的程序&#xff0c;请各位有能力的话带我熬过这凛冽的寒冬。 目前写出来的&#xff0c;有三个端&#xff1a;安卓TV端&#xf…

准备HarmonyOS开发环境

引言 在开始 HarmonyOS 开发之前&#xff0c;需要准备好开发环境。本章将详细指导你如何安装 HarmonyOS SDK、配置开发环境、创建 HarmonyOS 项目。 目录 安装 HarmonyOS SDK 配置开发环境 创建 HarmonyOS 项目 总结 1. 安装 HarmonyOS SDK HarmonyOS SDK 是开发 Harmo…

【Selenium2+python】自动化unittest生成测试报告

前言 批量执行完用例后&#xff0c;生成的测试报告是文本形式的&#xff0c;不够直观&#xff0c;为了更好的展示测试报告&#xff0c;最好是生成HTML格式的。 unittest里面是不能生成html格式报告的&#xff0c;需要导入一个第三方的模块&#xff1a;HTMLTestRunner 一、导…

leetcode1288. 删除被覆盖区间(java)

删除被覆盖区间 题目描述贪心法代码演示 题目描述 难度 - 中等 leetcode1288. 删除被覆盖区间 给你一个区间列表&#xff0c;请你删除列表中被其他区间所覆盖的区间。 只有当 c < a 且 b < d 时&#xff0c;我们才认为区间 [a,b) 被区间 [c,d) 覆盖。 在完成所有删除操作…

Docker使用数据卷挂载进行数据存储与共享

一、挂载和数据卷 在 Docker 中&#xff0c;挂载&#xff08;Mounting&#xff09;和数据卷&#xff08;Data Volumes&#xff09;是用于在容器和宿主机之间共享数据的机制。 挂载&#xff1a;将宿主机文件系统中的目录或文件与容器中的目录或文件进行关联的过程。数据卷&…

收入下降,亏损扩大,利润率急剧恶化,蔚来仍充满风险

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 蔚来第二季度财报分析 猛兽财经从蔚来&#xff08;NIO&#xff09;2023年第二季度财报中&#xff0c;获得的最大收获并不是该公司的收入下降或亏损扩大&#xff0c;而是由于价格竞争加剧&#xff0c;中国电动汽车行业整体上…

什么是安全运营中心(SOC),应该了解什么

安全运营中心&#xff08;SOC&#xff09; 是一种企业监视和警报设施&#xff0c;可帮助组织检测安全威胁、监视安全事件和分析性能数据以改进公司运营。 什么是安全运营中心&#xff08;SOC&#xff09; 安全运营中心&#xff08;SOC&#xff09;是一个中央监视和监视中心&a…

第二次作业

1.编写脚本for1.sh,使用for循环创建20账户&#xff0c;账户名前缀由用户从键盘输入&#xff0c;账户初始密码由用户输入&#xff0c;例如: test1、test2、test3、.....、 test10 编写脚本for1.sh 执行脚本&#xff1a;bash for.sh 2&#xff0c;编写脚本for2.sh,使用for循环,通…

模糊测试面面观 | 模糊测试是如何发现异常情况的?

协议模糊测试是一种用于评估通信协议、文件格式和API实现系统安全性和稳定性的关键技术。在模糊测试过程中&#xff0c;监视器扮演着关键角色&#xff0c;它们能够捕获异常情况、错误响应、资源利用等&#xff0c;为测试人员提供有价值的信息&#xff0c;有助于发现潜在漏洞和问…

ceph Monitor原理和代码流程介绍

Monitor介绍 Monitor在Ceph集群中扮演管理者的角色&#xff0c;维护了整个集群的状态&#xff0c;集群的状态被抽象成几个Map对象&#xff0c;包括monmap、osdmap、mdsmap、authmap、logmap等&#xff0c;保证集群的相关组件在同一时刻能够达成一致&#xff0c;相当于领导层。…