题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
思路:
1.前序遍历的第一个节点一定是根结点。前序遍历的一个节点要么是相邻前一个节点的左子树、右子树或者更靠近前面节点的右子树。如何确定前后相邻两个节点的关系需要中序遍历提供信息。
2.对于前序的一个节点,中序遍历对应的节点把节点分为左右两个部分,左边是左子树扩展出来的分支,右边是右子树扩展出来的分支。
3.如果左边节点被访问过,那么该节点左子树一定为空;相应的右边节点被访问过,那么该节点右子树为空。(判断的时候只需要判断相邻的左右节点,因为我们是以前序遍历的方式往下递归,父节点一定在左右子树访问前)
class Solution {
public:
int id=0;
TreeNode* Creat(vector<int>&pre,vector<int>&vin,int l,int r,vector<int>&vis){
//cout<<pre[k]<<' '<<l<<' '<<r<<endl;
if(l>r) return NULL;
TreeNode*rt=new TreeNode(pre[id]);
if(l==r) return rt;
int j;
for(int i=l;i<=r;++i){
if(vin[i]==pre[id]){
j=i;
break;
}
}
vis[j]=1;
if(j>l&&vis[j-1]==0){
++id;
rt->left=Creat(pre,vin,l,j-1,vis);
}
if(j<r&&vis[j+1]==0){
++id;
rt->right=Creat(pre,vin,j+1,r,vis);
}
return rt;
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
if(pre.size()!=vin.size()) return NULL;
if(pre.size()==0) return NULL;
TreeNode *root=new TreeNode(pre[0]);
int j,len=pre.size();
vector<int>vis(len,0);
for(int i=0;i<vin.size();++i){
if(pre[0]==vin[i]){
j=i;
break;
}
}
vis[j]=1;
if(j>0&&vis[j-1]==0){
++id;
root->left=Creat(pre,vin,0,j-1,vis);
}
if(j+1<pre.size()&&vis[j+1]==0){
++id;
root->right=Creat(pre,vin,j+1,len-1,vis);
}
return root;
}
};