重建二叉树(根据前序遍历和中序遍历构建二叉树)

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{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;
    }
};

猜你喜欢

转载自blog.csdn.net/u011721440/article/details/81506244