题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
解题思路:
根据前序遍历(根-左-右)和中序遍历(左-根-右)的特点,该题可以分为以下步骤:
1、根据前序遍历找到根节点
2、在中序遍历中找到根节点,由这个节点所在位置将数组分为左子树和右子树
3、建立一个新的树,并将根节点的值赋给它的根节点
4、将左、右子树分别当做一个新的树并存储起来,然后分别对左子树和右子树重复上述操作
整个过程实际上就是一个递归调用的过程
注意事项:
1、该题给的默认函数参数是vector,故求其长度时不能用pre.length,而应该用pre.size();
2、给出的函数是TreeNode* 类型,故新建的树的类型应该与其相同,返回时才不会出现错误
/**
* 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(pre.empty()|| vin.empty()|| pre.size()!= vin.size()) {
return NULL;
}
//在前序遍历pre中查找根节点,并确定其在Vin的位置
size_t index=0;
for(;index <=vin.size(); index++){
if(vin[index]==pre[0]){ //在vin中找到根节点时退出,此时index就是其在vin中的位置
break;
}
}
//创建新的根节点,并为其赋值
TreeNode* node=new TreeNode(pre[0]);
//根据中序遍历将根节点左右两侧一分为二,根节点的左侧为左子树,右侧为右子树
vector<int> pl,pr;
vector<int> vl,vr;
//将前序、中序中根节点的左右子树记录下来
for(size_t j=0; j<index; j++){
pl.push_back(pre[j+1]);
vl.push_back(vin[j]);
}
for(size_t j=index+1; j<vin.size(); j++){
pr.push_back(pre[j]);
vr.push_back(vin[j]);
}
//递归调用构建当前节点的左子树
node->left=reConstructBinaryTree(pl,vl);
//递归调用构建当前节点的右子树
node->right=reConstructBinaryTree(pr,vr);
return node;
}
};
参考文献:
https://blog.youkuaiyun.com/qq_33951180/article/details/72790549