标签:遍历 21 int 中序 节点 前序 二叉树 leetcode
21-3-3 leetcode题目:重建二叉树
数据结构与算法这东西是应该经过不断地勤学苦练才能保持手感的,尤其是对于我这样没有天赋的选手,刷题是不能停的,而且在刷题的同时,我还应该保持不断地记录,方能留下复盘的机会。这也是我为什么要开一个博客的原因。加油!
题目概述
输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/zhong-jian-er-cha-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
本题要注意的细节较为繁多,大概有如下几点:
- (前序遍历&&中序遍历)||(中序遍历&&后序遍历)是确定一颗唯一二叉树的充要条件。
- 前序遍历数组中首位数为二叉树的根节点。前序遍历的结果形式为`[ 根节点, [左子树的前序遍历结果], [右子树的前序遍历结果] ]`,且**分别处于左子树与右子树区间临界的两个值分别为左右子树的根节点。**
- 中序遍历的结果形式如下:`[ [左子树的中序遍历结果], 根节点, [右子树的中序遍历结果] ]`
在掌握这些小细节以后,就可以开始理解本题的思路了。
本题主要是应用了分治思想。你肯定知道:一用到分治思想就离不开递归。对于递归我是这样理解的:递归的执行形式为递出去再归回来,这主要是因为执行时函数储存再内存的栈中。分治法的递归特点就是取代,小范围的取代大范围的,从而分而治之。应用在二叉树上,便是树上的每个非叶子节点都可以看作一个根节点。这也是本题的核心思想。
那么现在开始考虑这道题:我们已知的条件在细节中讲过,前序遍历结果的首位是树的根节点,既然根节点是已知的,根节点左右两子树也是已知的,那么我们是否可以把这颗树对半劈开,将左子树与右子树都看作一颗新树,那么结合递归思想,我们不断地为新树分配左右子树就可以了!话不多说,上代码:
/**
* 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 {
private:
unordered_map<int,int> index;
public:
TreeNode* bulidOneTree(const vector<int>& preorder,const vector<int> inorder,int preorderLeft,int preorderRight,int inorderLeft,int inorderRight)
{
if(preorderLeft>preorderRight){ //递归不可少的结束条件,当树的节点用光时,程序自动结束。
return NULL;
}
int preorderRoot=preorderLeft;
int root=index[preorder[preorderRoot]];//确定根节点的位置。
TreeNode* treeRoot=new TreeNode(preorder[preorderRoot]);
int size=root-inorderLeft;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
treeRoot->left=bulidOneTree(preorder,inorder,preorderLeft+1,preorderLeft+size,inorderLeft,root-1);
// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
treeRoot->right=bulidOneTree(preorder,inorder,preorderLeft+size+1,preorderRight,root+1,inorderRight);
return treeRoot;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n=preorder.size();
for(int i=0;i<n;i++){
index[inorder[i]]=i;
}
return bulidOneTree(preorder,inorder,0,n-1,0,n-1);
}
};
标签:遍历,21,int,中序,节点,前序,二叉树,leetcode 来源: https://www.cnblogs.com/Leopard1214/p/14472301.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。