如何根据两个顺序构造⼀个唯⼀的⼆叉树?
本题思路根据Carl大佬整理,大家感兴趣的去关注一波。如果你想提升算法能力,只要跟住代码随想录每天题目的节奏,定会融会贯通,算法能力稳稳的提升一个台阶!
一、⾸先如何根据两个顺序构造⼀个唯⼀的⼆叉树?
1、以中序和后序遍历来说:
就是以 后序数组的最后⼀个元素为切割点,先切中序数组,然后根据中序左数组,反过来在切后序数组。⼀层⼀层切下去,每次后序数组最后⼀个元素就是节点元素。
1、接下来想到用递归法
(1)、如果后序数组大小为0,说明是空节点。返回NULL。
(2)、如果不为空,取后序数组最后一个元素作为节点元素。同时再判断一下后序数组大小是不是为1,为1说明是叶子节点直接返回。
(3)、接着找到后序数组最后一个元素在中序数组的位置,作为切割点。
(4)、把中序数组切割成中序左数组和中序右数组。
(5)、把后序数组切割成后序左数组和后序右数组。
(6)、递归处理左区间和右区间。
注意事项:
1、确定切割标准,找好边界值。
2、先切中序数组,因为切割点是后序数组最后一个元素。
3、后序数组没有明确的切割点,但是要记得中序数组大小一定等于后序数组大小。
现在我们把中序数组切成了中序左数组和中序右数组,那么后序数组就可以按照中序左数组的大小来切割,得到后序左数组和后序右数组。
递归法(容器分割)
class Solution{private:TreeNode* traversal(vector<int>&inorder,vector<int>&postorder) {//第一步,判断后序数组大小是否为0if(postorder.size()==0) return NULL;//第二步,找到后序遍历数组最后⼀个元素,就是当前的中间节点,接着判断是不是叶子节点int rootValue=postorder[postorder.size()-1];TreeNode* root=newTreeNode(rootValue);if(postorder.size()==1) return root;//第三步,找到中序遍历的切割点int delimiterIndex;//1从0开始,因为是容器里面装着数组for(delimiterIndex=0;delimiterIndex<inorder.size();delimiterIndex++) {if(inorder[delimiterIndex]==rootValue)break;}//第四步,切割中序数组//左闭右开区间:[0, delimiterIndex)vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);// [delimiterIndex + 1, end)vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end() );// postorder舍弃末尾元素postorder.resize(postorder.size()-1);//第五步,切割后序数组//依然左闭右开,注意这⾥使⽤了左中序数组⼤⼩作为切割点,[0, leftInorder.size)vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());// [leftInorder.size(), end)vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());root->left=traversal(leftInorder,leftPostorder);root->right=traversal(rightInorder,rightPostorder);return root;
}
public:TreeNode* buildTree(vector<int>&inorder,vector<int>&postorder{if(inorder.size()==0||postorder.size()==0) return NULL;returntraversal(inorder,postorder);}
};
如上的代码性能并不好,因为每层递归都定义了新的vector(就是数组),既耗时⼜耗空间,但上⾯的代码是最好理解的。
递归法(下表索引分割)
思路是⼀样的,只不过不⽤重复定义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 nullptr;int rootValue=postorder[postorderend-1];TreeNode* root=new TreeNode(rootValue);if(postorderend-postorderbegin==1) return root;//找到分割点在中序数组的位置int delimiterIndex;for(delimiterIndex=inorderbegin;delimiterIndex<inorderend;delimiterIndex++){ ///1 ,注意标记法的开始和结束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);///2//后序右数组,左闭右开[rightPostorderBegin, rightPostorderEnd)int rightPostorderbegin=postorderbegin+(delimiterIndex-inorderbegin);///3int rightPostorderend=postorderend-1;///4 排除最后⼀个元素,已经作为节点了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()==NULL||postorder.size()==NULL) return nullptr;return traversal(inorder,0,inorder.size(),postorder,0,postorder.size());}
};
2、以前序和中序遍历
/*** Definition for a binary tree node.* 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 {private:TreeNode* traversal(vector<int>& preorder,int preorderBegin,int preorderEnd,vector<int>& inorder,int inorderBegin,int inorderEnd ){if(preorderBegin==preorderEnd) return NULL;int rootValue=preorder[preorderBegin];TreeNode* root=new TreeNode(rootValue);if(preorderEnd-preorderBegin==1) return root;int delimiterIndex;for(delimiterIndex=inorderBegin;delimiterIndex<inorderEnd;delimiterIndex++){if(inorder[delimiterIndex]==rootValue) break;}//切割中序数组int leftInorderBegin=inorderBegin;int leftInorderEnd=delimiterIndex;int rightInorderBeigin=delimiterIndex+1;int rightInorderEnd=inorderEnd;//切割前序数组int leftPreorderBegin=preorderBegin+1;int leftPreorderEnd=preorderBegin+(delimiterIndex-inorderBegin)+1;int rightPreorderBeigin=preorderBegin+(delimiterIndex-inorderBegin)+1;int rightPreorderEnd=preorderEnd;root->left=traversal(preorder,leftPreorderBegin,leftPreorderEnd,inorder,leftInorderBegin,leftInorderEnd);root->right=traversal(preorder,rightPreorderBeigin,rightPreorderEnd,inorder,rightInorderBeigin,rightInorderEnd);return root;}
public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if(preorder.size()==NULL||inorder.size()==NULL) return NULL;return traversal(preorder,0,preorder.size(),inorder,0,inorder.size());}
};
如何根据两个顺序构造⼀个唯⼀的⼆叉树?相关推荐
- 数据结构笔记:二叉树的构造(根据遍历顺序构造二叉树)
目录 给出先序遍历序列和中序遍历序列可以唯一确定二叉树 给出后序遍历序列和中序遍历序列可以唯一确定二叉树 题: 给出先序遍历序列和中序遍历序列可以唯一确定二叉树 给出后序遍历序列和中序遍历序列可以唯一 ...
- 数据结构——二叉树的修改与构造
数据结构--二叉树的修改与构造 一.修改二叉树 226. 翻转二叉树 1.前/后序递归 2.广度优先搜索迭代 3.拓展:修改中序遍历 / 中序统一迭代写法 114. 二叉树展开为链表 二.构造二叉树 ...
- LeetCode专题:树与回溯(完结,已更50题)
目录 LeetCode二叉树的基本遍历(难): 写在前面: 前序遍历: Morris遍历: 中序遍历: Morris遍历: 后序遍历: Morris遍历: 二叉树前中后迭代方式同一写法: 鸣谢: Le ...
- 虚继承c语言例子,C/C++ 多继承{虚基类,虚继承,构造顺序,析构顺序}
C/C++:一个基类继承和多个基类继承的区别 1.对多个基类继承会出现类之间嵌套时出现的同名问题,如果同名变量或者函数出现不在同一层次,则底层派生隐藏外层比如继承基类的同名变量和函数,不会出现二义性, ...
- 第十章 C++编程之构造顺序
第十章 C++编程之构造顺序 10.1 解释概念 简单说,构造函数就是在定义某个类的时候会调用的一个函数,默认构造不带参,其余构造函数可以自己实现. 10.2 示例代码 1.示例代码 #include ...
- C++类变量构造和析构顺序
文章目录 继承关系上构造析构顺序 同一级别的构造顺序 析构的顺序则刚好是构造顺序的逆序 继承关系上构造析构顺序 有类静态成员变量优先构造静态变量 与声明的顺序无关,与继承关系也无关,只是按照定义的先后 ...
- C++构造函数及析构函数的调用顺序
简单来说,其构造函数的顺序就一句话: 基类构造函数 -> 成员的构造函数 -> 构造函数体内语句 看下面一个代码示例: #include <iostream>using nam ...
- 中石油训练赛 - Insertion Order(二叉搜索树+构造)
题目大意:构造出一个长度为 n 的排列,使得按照这个顺序构造出的二叉搜索树的高度为 k 题目分析:知道 n 的大小后不难算出其可以构造的二叉搜索树高度的可行范围,下限是一棵满二叉树,这个利用倍增很快就 ...
- Python treelib库创建多叉树的用法介绍
Python treelib库创建多叉树的用法介绍 treelib 库是一个 Python 的第三方库.这个库实现了一些多叉树相关的常用方法. 一.安装treelib pip install tree ...
最新文章
- 阿里Java开发手册——如何优化数据库?
- 电量计在手持设备中的实现
- 报警服务器物理内存,从内存告警谈ESXi主机内存管理——内存构成
- ie浏览器打字不显示文字框命令
- 那些一心想要离开 BAT 的人,后来怎么样了?
- java对list里面按照分数排名_近3年全国高校高考录取分数线排名,600分以上高校55所...
- python语言程序设计实践教程上海交通大学出版社的答案_高等教育出版社出版社c语言程序设计实践教程习题参考答案...
- python中pip下载过慢问题
- TM2013自定义消息记录保存目录
- c语言 虚拟时钟 指针,指针式模拟时钟.doc
- 吾爱破解新手教程(1)- 破解,逆向,安全
- html中onfocus作用,HTML onfocus用法及代码示例
- 502粘到手上变硬了怎么办_502胶水把手黏住了怎么办
- linux_zsh/oh my zsh 版本检查/使用帮助(check and update)/安装最新版zsh
- JAVA--建立一个可输入个人信息的窗口
- 专享策略02 | 商品股指通用套利策略(一)
- P528 List接口常用实现类的对比及源码分析
- java中接口的优点和缺点
- 计算机 无法进入pe,U盘重装系统|无法进入韩博士PE系统怎么办
- SmallUI-小ui 前端ui组件库(好用的组件千篇一律,轻巧的组件万里挑一)
热门文章
- 让那些为Webkit优化的网站也能适配IE10(转载)
- HTML标签语义化——使用b标签,还是strong标签
- VC里的#define new DEBUG_NEW
- word通配符使用法详解
- Linux下GCC的安装,GCC链接外部库
- MySQL count(1) count(*) 比较 详解
- RxSwift之深入解析map操作符的底层实现
- LDC1000学习资料
- Martix工作室考核题 —— 2019-3-8 第三题
- 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1109:开关灯