【Day-31慢就是快】代码随想录-二叉树-中序和后序遍历构造二叉树

news2024/10/3 8:19:34

根据一棵树的中序遍历与后序遍历构造二叉树。

注意: 你可以假设树中没有重复的元素。

思路


首先知道怎么画,然后写代码流程。

以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。

需要层层切割,获得节点,可以考虑递归。

来看一下一共分几步:

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

代码框架如下:

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(postorder.size() == 0) return NULL;

        int rootVal = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootVal);

        if(postorder.size() == 1) return root;
        //第三步 找切割点
        int delimiterIndex;
        for(delimiterIndex=0;delimiterIndex < inorder.size();delimiterIndex++){
            if(inorder[delimiterIndex] == rootVal) break;
        }

        //第六步 继续构建
        root->left = buildTree();
        root->right = buildTree();
    }
};

如何准确切割中序和后序数组,找对边界值。

在切割过程中会出现四个区间,要保证区间表示全程不变性。

先根据后序数组的最后一个元素来切割中序数组。

然后根据中序数组的前后部分长度来切割后序数组。(因为中序和后序切割部分前后长度一致)

  • 先切割中序部分:
//中序切割部分  左闭右开区间
        vector<int> leftInorder(inorder.begin(), inorder.begin()+delimiterIndex);
        vector<int> rightInorder(inorder.begin()+delimiterIndex+1, inorder.end());
  • 切割后序部分
//后序部分
        postorder.resize(postorder.size()-1);
        vector<int> leftPostorder(postorder.begin(), postorder.begin()+leftInorder.size());
        vector<int> rightPostorder(postorder.begin()+leftInorder.size(), postorder.end());

完整代码:

class Solution {
public:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder)
    {
        if(postorder.size() == 0) return NULL;

        int rootVal = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootVal);

        if(postorder.size() == 1) return root;
        //第三步 找切割点
        int delimiterIndex;
        for(delimiterIndex=0;delimiterIndex < inorder.size();delimiterIndex++){
            if(inorder[delimiterIndex] == rootVal) break;
        }
        //中序切割部分  左闭右开区间
        vector<int> leftInorder(inorder.begin(), inorder.begin()+delimiterIndex);
        vector<int> rightInorder(inorder.begin()+delimiterIndex+1, inorder.end());
        //后序部分
        postorder.resize(postorder.size()-1);
        vector<int> leftPostorder(postorder.begin(), postorder.begin()+leftInorder.size());
        vector<int> rightPostorder(postorder.begin()+leftInorder.size(), postorder.end());

        //第六步 继续构建
        root->left = traversal(leftInorder, leftPostorder);
        root->right = traversal(rightInorder, rightPostorder);

        return root;
    }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size() == 0 || postorder.size() == 0) return NULL;
        return traversal(inorder, postorder);
    }
};

下面用索引下标,省去vector.

class Solution {
private:
    // 中序区间:[inorderBegin, inorderEnd),后序区间[postorderBegin, postorderEnd)
    TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& postorder, int postorderBegin, int postorderEnd) {
        if (postorderBegin == postorderEnd) return NULL;

        int rootValue = postorder[postorderEnd - 1];
        TreeNode* root = new TreeNode(rootValue);

        if (postorderEnd - postorderBegin == 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;

        // 切割后序数组
        // 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
        int leftPostorderBegin =  postorderBegin;
        int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 终止位置是 需要加上 中序区间的大小size
        // 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
        int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);
        int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了

        root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  postorder, leftPostorderBegin, leftPostorderEnd);
        root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);

        return root;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        // 左闭右开的原则
        return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());
    }
};

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

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

相关文章

最佳策略app平台传出的绝密理财法,这是给散户们的好机会

昨天&#xff0c;记者在走访各大超市的时候发现一个奇怪的现象&#xff1a;普遍的市民朋友在选购商品的时候基本上都会选择那些打折促销的&#xff0c;有些促销的商品甚至是很久之后才会用的&#xff0c;他们也会给带上。而对于那些不打折或者价格高昂的商品&#xff0c;基本上…

入耳耳机对耳朵有损害吗?入耳耳机和骨传导耳机哪个好?

先说结论&#xff0c;入耳式耳机对耳朵是有伤害的&#xff0c;骨传导耳机相比于入耳式耳机可以保护更好的保护耳朵健康。 在日常中&#xff0c;经常会看到有佩戴耳机的时尚青年&#xff0c;他们戴着耳机刷视频、听音乐&#xff0c;陶醉在自己的小世界中&#xff0c;但是长时间…

项目经理常用的6种工具,让项目管理变得更高效

项目管理是一个复杂的过程&#xff0c;因为不仅要管人管事&#xff0c;会遇到各种问题&#xff0c;因此用什么工具管理项目&#xff0c;对项目管理是一个很好地辅助&#xff0c;让项目管理变得更有效、更高效。 1、甘特图 甘特图将一个大型项目划分为几个阶段&#xff0c;并…

飞凌嵌入式受邀亮相2023中国国际数字经济博览会

9月6日&#xff0c;由工信部、国家发改委和河北省人民政府共同主办的2023中国国际数字经济博览会在石家庄国际会展中心&#xff08;正定&#xff09;开幕&#xff0c;近500家参展企业携自家的“黑科技”展品集中亮相&#xff0c;赋能智慧应用新场景&#xff0c;为观众带来了一场…

【1】DDR---容量计算

1、容量计算 density&#xff1a;芯片容量&#xff0c;bit为单位 depth&#xff1a;地址空间&#xff0c; width&#xff1a;数据位宽 densitydepth*width 2、三星DDR 4Gbit&#xff08;总容量&#xff09;256M&#xff08;地址空间&#xff09;*16&#xff08;位宽&#xff…

GOOGLE SRE 运维模式解读

一、SRE核心是什么 我总结下来是&#xff1a;通过软件工程的方式开发&#xff08;GOOGLE规定SRE团队必须将50%的精力花在真实的开发工作上&#xff09;一些自动化的工具系统来解放传统运维工程师大量重复和手工操作&#xff0c;从而让新生代的SRE工程师有更多的时间&#xff1…

用户促活留存新方式——在APP中嵌入小游戏

随着APP同类产品的不断出现&#xff0c;APP开发者们面临着激烈的竞争&#xff0c;很多APP下载后被新的APP取代&#xff0c;获客成本越来越高。同时开发者还会面临用户粘性差、忠诚度低、用完即走、留存困难&#xff0c;商业化价值被大大缩减。 在APP中植入小游戏来提高用户活跃…

无涯教程-JavaScript - BESSELJ函数

描述 BESSELJ函数返回贝塞尔函数Jn(x)。 语法 BESSELJ(X, N)争论 Argument描述Required/OptionalXThe value at which to evaluate the function.RequiredNThe order of the Bessel function. If n is not an integer, it is truncated.Required Notes 如果x为非数值,则B…

亚马逊鲲鹏AI智能养号好用吗?怎么使用的?

亚马逊鲲鹏AI智能一键养号可以根据AI功能页面的姓名、年龄、职业、爱好等生成一批不同的AI角色&#xff0c;账号绑定这些角色后就可以自动浏览进行养号了。 功能特点 1、自动生成AI姓名、随机选择角色性别、自由设置AI年龄 2、根据勾选的AI职业、AI爱好进行随机生成AI关键词进…

pdf文档怎么压缩小一点?文件方法在这里

在日常工作和生活中&#xff0c;我们经常会遇到需要上传或者发送pdf文档的情况。但是&#xff0c;有时候pdf文档的大小超出了限制&#xff0c;需要我们对其进行压缩。那么&#xff0c;如何将pdf文档压缩得更小一点呢&#xff1f;下面&#xff0c;我将介绍三种方法&#xff0c;让…

【校招VIP】测试计划之hashmap分析

考点介绍&#xff1a; HashMap是Java程序员使用频率最高的用于映射键值对(key和value)处理的数据类型。随着JDK版本的跟新&#xff0c;JDK1.8对HashMap底层的实现进行了优化&#xff0c;列入引入红黑树的数据结构和扩容的优化等。 测试计划之hashmap分析-相关题目及解析内容可…

雷士明轩好用吗?测评师对比横评书客、雷士、米家哪款好

如今&#xff0c;大多数人的日常工作和学习都离不开电子设备&#xff0c;长时间盯着屏幕容易造成眼睛疲劳和视力下降。全国近视率占多数的还是青少年&#xff0c;护眼台灯作为一种照明设备&#xff0c;具有调节光线亮度和色温的功能&#xff0c;可以有效减少眼睛的疲劳&#xf…

Java【多线程】Callable 是什么, 如何使用并理解 Cllable, 和 Runnable 有什么区别?

文章目录 前言一、Callable 是什么&#xff1f;二、不使用 Callable 如何创建“有返回值的”线程&#xff1f;三、如何使用 Callable&#xff1f;四、如何理解 Callable&#xff1f;总结 前言 &#x1f4d5;各位读者好, 我是小陈, 这是我的个人主页 &#x1f4d7;小陈还在持续努…

将钉钉机器人小程序从一个公司迁移至另一个公司的步骤

引言&#xff1a; 由于我们以前开发的钉钉小程序都在一个公司&#xff0c;想在想应用到另一个公司&#xff0c;这就牵扯出了关于钉钉小程序迁移方面的具体步骤。下面是具体步骤&#xff1a; 1、创建一个钉钉小程序 在这一步你需要有钉钉开放平台的开发者权限&#xff0c;具体…

uniapp使用@microsoft/signalr(报错“ReferenceError: require is not defined“)

后台老哥要用微软的signalr&#xff0c;总结了一些经验和问题 引入方法 1、npm npm i microsoft/signalr 2、下载他的js或者cdn <script src"https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>在uniapp中&…

无涯教程-JavaScript - BITRSHIFT函数

描述 BITRSHIFT函数返回一个右移指定位数的数字。 语法 BITRSHIFT (number, shift_amount)争论 Argument描述Required/OptionalnumberMust be an integer greater than or equal to 0.Requiredshift_amountMust be an integer.Required Notes 向右移动数字等效于从数字的二…

向你推荐 6 个很酷很实用的 Python 编码技巧

近年来&#xff0c;Python 编码技能的需求不断增长。在本作者前面文章介绍的多种基础上&#xff0c;我们整理了 6 个很酷很实用的 Python 编码技巧&#xff0c;您可以使用它们来改进代码、提高 Python 技能。 1.变量 在 Python 中&#xff0c;我们不需要使用临时变量&#xf…

stc单片机外部中断+EC11编码器实现计数功能

stc单片机外部中断+EC11编码器实现计数功能 🎬 串口输出测试效果: 📑EC11编码器原理图: 🍁EC11编码器输出信号说明: 📗检测说明: 📑以EC11-A信号作为一个时钟基准信号,检测到EC11-A之后,再去判断B的动作,一个相对的电平。当检测到A信号下降沿触发后,检测…

无涯教程-JavaScript - BITXOR函数

描述 BITXOR函数返回两个数字的按位" XOR"。 语法 BITXOR (number1, number2)争论 Argument描述Required/Optionalnumber1Must be greater than or equal to 0.Requirednumber2Must be greater than or equal to 0.Required Notes BITXOR返回一个十进制数字,该数…

Chrome 108版(64-bit 108.0.5359.125)网盘下载

还在用Selenium的朋友们注意了&#xff0c;目前Chrome的最新版是116&#xff0c;而官方的Chromedriver只支持到115版。 可惜Google不提供旧版Chrome的下载方式&#xff0c;需要旧版的很难回去了。如果真的想要旧版的Chrome&#xff0c;只能民间自救。 我在2022年12月备份了C盘…