目录

  • 1、106题目
  • 2、参考思路:递归切割数组
  • 3、105题目
  • 4、同样思路的代码

1、106题目

2、参考思路:递归切割数组

代码参考:公众号:代码随想录
后序数组+中序数组
以 后序数组(左右中)的最后一个元素作为切割点,先切中序数组,根据中序数组反过来再切割后序数组。一层一层切割下去,每次后序数组最后一个元素就是结点元素。
先序数组+中序数组
以 先序数组(中左右)的第一个元素作为切割点,先切中序数组,根据中序数组反过来再切割先序数组。一层一层切割下去,每次先序数组第一个元素就是结点元素。
先序数组+后序数组为何不能构造一个唯一的二叉树
对于一个二叉树,并不是说给出了先序和后序就是无法唯一确定的。只是说,在某些情况下,不能唯一确定。
即:

当二叉树中某个节点仅仅只有一个孩子节点的时候,就无法根据其先序和后序唯一的确定一个二叉树。
更详细的解释请看这个链接:
关于二叉树先序遍历和后序遍历为什么不能唯一确定一个二叉树分析
我的理解:由于中序遍历的存在,你只需要找到中间结点就可以十分迅速并且准确地确定它的左右孩子,而后序、前序遍历则没有这个特征。
举例:给定序列1 2 3 4,且中间结点是3。
中序遍历,则可得到:1、2是3结点的左子树的结点、4是3结点的右子树的结点
给定序列1 2 3 4,且中间结点是1。
先序遍历,你不知道234三个结点究竟是怎样分布在左右子树上的,可能是:
【234】【】;
【23】【4】;
【2】【34】;
【】【234】;
后序遍历同理。

递归分析:

1、如果数组大小为0的话,说明就是空结点。
2、如果不为空,那么取后序数组最后一个元素作为结点元素
3、找到后序数组最后一个元素在中序数组的位置,作为切割点
4、切割中序数组,切割成中序左数组和中序右数组
5、切割后序数组,切成后序左数组和后序右数组
6、递归处理左区间和右区间

关于构造二叉树的方法,回顾;
LintCode 375. 克隆二叉树(深复制)

TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {//step1if(postorder.size() == 0 ) return NULL;//step2:后序遍历数组的最后一个元素就是当前的中间结点int rootVal = postorder[postorder.size()-1];TreeNode* NewRoot = new TreeNode(rootVal);//如果是叶子结点,返回结点if(postorder.size() == 1) return NewRoot;//step3:寻找切割点int CutIndex ;for(CutIndex=0;CutIndex<inorder.size();CutIndex++){if(inorder[CutIndex] == rootVal) break;}//step4:切割中序数组,得到中序左数组和中序右数组//step5:切割后序数组,得到后序左数组和后序右数组//step6:/*root->left = traversal(中序左数组,后序左数组);root->left = traversal(中序右数组,后序右数组);*/}

切割的原则我们遵循左闭右开(右边的不取).
切割中序数组

//找到中序遍历的切割点
int CutIndex ;
for(CutIndex=0;CutIndex<inorder.size();CutIndex++)
{if(inorder[CutIndex] == rootVal) break;
}
//区间形式:[x1,x2);
vector<int> leftInorder(inorder.begin(),inorder.begin()+CutIndex );
vector<int> rightInorder(inorder.begin()+CutIndex+1,inorder.end() );

切割后序数组
1、后序数组没有明确的切割元素来进行左右切割。
2、中序数组的大小和后序数组的大小相同。
3、我们已经将中序数组切割成了左、右两个子数组了。
4、舍弃掉后序数组末尾元素,因为这个元素是中间结点

//舍弃末尾元素
postorder.resize(postorder.size() -1 );
//左闭右开,使用了左中序数组大小作为切割点:[0,leftorder.size()]
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);

代码

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {//step1if(postorder.size() == 0 ) return NULL;//step2:后序遍历数组的最后一个元素就是当前的中间结点int rootVal = postorder[postorder.size()-1];TreeNode* NewRoot = new TreeNode(rootVal);//如果是叶子结点,返回结点if(postorder.size() == 1) return NewRoot;//step3:寻找切割点int CutIndex ;for(CutIndex=0;CutIndex<inorder.size();CutIndex++){if(inorder[CutIndex] == rootVal) break;}//step4:切割中序数组,得到中序左数组和中序右数组//区间形式:[x1,x2);vector<int> leftInorder(inorder.begin(),inorder.begin()+CutIndex );vector<int> rightInorder(inorder.begin()+CutIndex+1,inorder.end() );//step5:切割后序数组,得到后序左数组和后序右数组//舍弃末尾元素postorder.resize(postorder.size() -1 );//左闭右开,使用了左中序数组大小作为切割点:[0,leftorder.size()]vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());//step6:NewRoot->left = traversal(leftInorder,leftPostorder);NewRoot->right= traversal(rightInorder,rightPostorder);return NewRoot;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if(inorder.size() == 0 || postorder.size() == 0) return NULL;return traversal(inorder,postorder);}
};

分析:每层递归都定义了数组,耗时间也耗空间。
下面给出用下标索引分割代码,不需要重新构造数组了。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:
// 中序区间:[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;}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());}
};

3、105题目

4、同样思路的代码

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/
class Solution {public:
// 中序区间:[inorderBegin, inorderEnd),先序区间[preorderBegin, preorderEnd)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];TreeNode* 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;}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());}
};

leetcode 106. 从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树思考分析相关推荐

  1. 【必拿下系列】106. 从中序与后序遍历序列构造二叉树105从前序与中序遍历序列构造二叉树

    两题各自的链接放这里了: 链接: 106 链接: 105 106.从中序与后序遍历序列构造二叉树 如果你是不知道理论的,那就得仔细分析了, 举个例子: 输入:inorder = [9,3,15,20, ...

  2. 105从前序与中序遍历序列构造二叉树 106 从中序与后序遍历序列构造二叉树 (递归 + 哈希)

    引言 这两道题主要是考察二叉树遍历的掌握,即由前序和中序推出原二叉树,由后序和中序推出原二叉树,这里先来说一下推导过程: 前序和中序 知道前序遍历和中序遍历,如何推原二叉树?(直接是结论,可以自行推导 ...

  3. LeetCode 刷题之旅(2020.05.22)——105. 从前序与中序遍历序列构造二叉树(中)

    LeetCode 刷题之旅(2020.05.22)--105. 从前序与中序遍历序列构造二叉树(中) 题目: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如, ...

  4. 【LeetCode】【HOT】105. 从前序与中序遍历序列构造二叉树(哈希表+递归)

    [LeetCode][HOT]105. 从前序与中序遍历序列构造二叉树 文章目录 [LeetCode][HOT]105. 从前序与中序遍历序列构造二叉树 package hot;import java ...

  5. 收藏||二叉树的遍历:颜色标记法(前序、中序、后序通用)

    参考力扣题解 作者:hzhu212 链接:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/solution/yan-se- ...

  6. C/C++编程笔记:数据结构二叉树的查找(前序、中序、后序、层序遍历)

    建立一棵含有n个结点的二叉树,采用二叉链表存储: 输出前序.中序.后序..层序遍历该二叉树的遍历结果. 定义二叉树的数据类型--二叉树结点结构体BiNode.建立二叉链表可以采用扩展二叉树的一个遍历序 ...

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

    难度:中等 频次:68 题目: 给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点 ...

  8. 50. Leetcode 105. 从前序与中序遍历序列构造二叉树 (二叉树-二叉树构建)

    给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点.示例 1:输入: preord ...

  9. LeetCode OJ:Construct Binary Tree from Preorder and Inorder Traversal(从前序以及中序遍历结果中构造二叉树)...

    Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that ...

最新文章

  1. 怎样才算全面的分类?
  2. 日志系统新贵 Loki,真香!!
  3. Exchange server 2013 安装部署初体验
  4. matlab没有int函数,matlab 未定义与 'char' 类型的输入参数相对应的函数 'int'。
  5. MyBatis之Mapper动态代理开发
  6. 平面单腿机器人跳跃控制研究——后续内容
  7. text-overflow:ellipsis溢出显示省略号兼容所有浏览器的解决办法
  8. 无锡东亭计算机培训班,锡山区东亭办公自动化培训、电脑培训班有哪些?
  9. 巴什博弈:取石子游戏
  10. FISCO BCOS PBFT是什么 基础流程
  11. linux禁止root用户远程登录,linux禁止root用户远程登录
  12. typora快捷键大全
  13. android9三星功能,三星开启安卓9.0测试:One UI Beta计划
  14. mpvue微信小程序动画_mpvue 与微信小程序的火花
  15. 【已解决】找不到某服务器 IP 地址
  16. 软文营销文案写作如何用创意编制想象力“城堡”
  17. git恢复某个文件到上一个提交版本
  18. 085 《穷查理宝典》简记
  19. 刚上线的App该如何做好ASO优化?
  20. 什么是阻抗?影响阻抗的因素有哪些?

热门文章

  1. PHPcms框架的Webshell
  2. 马秀丽C语言程序设计答案pdf,C语言程序设计清华大学马秀丽刘志妩科后习题9答案.doc...
  3. mysql怎么给表设置查询语句_MySQL查询语句简单操作示例
  4. JS ES6中的箭头函数(Arrow Functions)使用
  5. php ajax实现分页效果
  6. vue笔记(四)注册组件,路由,vuex
  7. eureka-7-多网卡下的ip选择
  8. DBMS-数据库设计与E-R模型:E-R模型、约束、E-R图、E-R扩展特性、E-R图转换为关系模式、UML建模...
  9. python中+=和=+的区别
  10. # 20155337 2017-2018-1 《信息安全系统设计基础》第二周课堂实践+myod