剑指offer7:重建二叉树

 

一般遇到遍历树,我们可以尝试找出规律,然后递归。

我们来看看前序遍历和中序遍历的格式:

前序:

中序:

看前序,我们可以得知,前序遍历序列的第一个元素是根,又由于题目中说,前序遍历和中序遍历结果中不含重复的数字,所以我们用前序的第一个元素可以在中序遍历中定位唯一一个根的位置,然后从中序遍历中可以划分出左子树的部分和右子树的部分。

接着,我们怎么继续递归呢,由于在中序遍历中划分出了左右子树,所以我们获取一些更多的信息以便我们后面的遍历,即可以获取左子树的区间长度和右子树的区间长度,在前序遍历里边再划分出对应的左子树的前序序列和右子树的前序序列,这样是不是就有点递归的感觉了?

代码如下所示:

class Solution {
public:
    //运用哈希 来存储“根”的下标
    unordered_map<int, int> index;
    //这里的const是细节
    TreeNode* myBuildTree(const vector<int>& preorder,const vector<int>& inorder,int preorder_left,int preorder_right,int inorder_left,int inorder_right)
    {
        if(preorder_left>preorder_right || inorder_left>inorder_right)
            return NULL;
        
        int preorder_index=preorder_left;
        int inorder_index=index[preorder[preorder_index]];
        int len=inorder_index-inorder_left;
        TreeNode *root=new TreeNode(preorder[preorder_index]);
        root->left=myBuildTree(preorder,inorder,preorder_left+1,preorder_left+len,inorder_left,inorder_index-1);
        root->right=myBuildTree(preorder,inorder,preorder_left+len+1,preorder_right,inorder_index+1,inorder_right);
        
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) 
    {
        int n=preorder.size();
        for(int i=0;i<n;++i)
        {
            index[inorder[i]]=i;
        }
        return myBuildTree(preorder,inorder,0,n-1,0,n-1);
    }
};

啊啊,然后还有另外一种递归的写法,就是直接创建vector的数组拷贝:

/**
 * 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) {
        int n=pre.size();
        int m=vin.size();
        if(n==0||m==0){
            return NULL;
        }
        TreeNode *node=new TreeNode(pre[0]);
        for(int i=0;i<m;++i){
            if(pre[0]==vin[i]){
                vector<int> leftpre(pre.begin()+1, pre.begin()+i+1);
                vector<int> leftvin(vin.begin(), vin.begin()+i);
                node->left=reConstructBinaryTree(leftpre, leftvin);
                vector<int> rightpre(pre.begin()+i+1, pre.end());
                vector<int> rightvin(vin.begin()+i+1, vin.end());
                node->right=reConstructBinaryTree(rightpre, rightvin);
                break;
            }
        }
        return node;
    }
};

思路大体都是一样的,但是开销可能不一样,第一个的开销应该要小一些

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值