题目描述:
给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。
提示:
1.vin.length == pre.length
2.pre 和 vin 均无重复元素
3.vin出现的元素均出现在 pre里
4.只需要返回根结点,系统会自动输出整颗树做答案对比
题解
思路:二叉树的前序遍历:根左右;中序遍历:左根右
由前序遍历知道根节点之后,能在中序遍历上划分出左子树和右子树。分别对中序遍历的左右子树递归进行这一过程即可建树。在划分过程中,重要的是对二叉树进行分割,既然要分割,就需要提前直到根节点的位置。
图示过程,引用Maokt
代码
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if (0 == pre.size() || vin.empty())
return NULL;//空树,也作为递归调用的出口
//前序遍历,第一个元素即为根节点元素,通过构造函数创建根节点
TreeNode* root = new TreeNode(pre[0]);
// 从后序遍历中找到根节点的位置,从这个位置开始将中序遍历的结果分为
// 左子树和右子树
int index = 0;//找到根节点在中序遍历中的位置
for (index;index<vin.size();index++) {
if (vin[index] == pre[0])//找到中序遍历中根节点的位置
break;
}
//使用vector拷贝构造函数分别得到递归调用时需要用到的四个vector区间
//构造四个数组,分别存放先序遍历中的左子树和右子树,以及中序遍历中的左子树和右子树
//注意:拷贝构造是左取右不取
// vector<int> pre_left(pre.begin()+1,pre.begin()+index+1);
// vector<int> pre_right(pre.begin()+index+1,pre.end());
// vector<int> vin_left(vin.begin(),vin.begin()+index);
// vector<int> vin_right(vin.begin()+index+1,vin.end());
//上述代码也可直接进行,如
//左子树
vector<int> pre_left,pre_right,vin_left,vin_right;
for(int i = 0;i<index;i++){
pre_left.push_back(pre[i+1]);
vin_left.push_back(vin[i]);
}
//右子树
for(int i =index+1;i<pre.size();i++){
pre_right.push_back(pre[i]);
vin_right.push_back(vin[i]);
}
//递归构造左右子树
root->left=reConstructBinaryTree(pre_left, vin_left);
root->right=reConstructBinaryTree(pre_right, vin_right);
return root;
}
};