剑指Offer第四题:重建二叉树

记录下卡住的题目

题目描述

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。

思路:
1.先序第一个就是根节点
2.利用根节点可以把中序的成员分成左节点和右节点
3.左边节点所有成员个数确定后,可以在先序中找到一组属于左节点的数,临时称为L1,右边为R1
4.L1中第一个数便是L1的根节点,R1同理。
5.接着同样进行第二三步,利用中序的成员,就能分成左边组L2和右边组R2,若无就为空
6.接着继续找到L2第一个为根节点,R2同理,直到LN和RN个数均为0

实际上按照思路来说,难的地方应该是最后的递归和递归边界问题,可惜本人中间那几步写的时候由于不注意,还是写错了,导致debug了好久,还一度怀疑是递归写错了。

C++代码如下(刷题平台:牛客网):

class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
         if(pre.size() == 0)//递归终止条件
            return NULL;
        TreeNode * root = new TreeNode(pre.front());//根节点
        
        //求得左右先序中序
        vector<int>m_lv;//左边,中序
        vector<int>m_rv;//右边,中序
        vector<int>::iterator itr_v;
        int flag =0;
        for(itr_v=vin.begin();itr_v != vin.end();itr_v++)
        {
              if(*itr_v == root->val)
                  flag =1;
              else
              {
                  if(flag ==0)
                      m_lv.push_back(*itr_v);
                  else
                      m_rv.push_back(*itr_v);
              }
        }
        vector<int>m_lp;//左边,先序
        vector<int>m_rp;//右边,先序
        vector<int>::iterator itr_p;
        int count=0;
        for(itr_p=pre.begin()+1;itr_p != pre.end();itr_p++,count++)
        {
             if(count<m_lv.size())
                 m_lp.push_back(*itr_p);
              else
                 m_rp.push_back(*itr_p);
        }
        
        root->left = reConstructBinaryTree(m_lp,m_lv);
        root->right = reConstructBinaryTree(m_rp,m_rv);

        return root;
        
    }

};

简化版(第二次做更新)

class Solution {
public:
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        if(pre.size() == 0)
            return NULL;
        int len = pre.size();
        TreeNode* root = new TreeNode(pre[0]);//根节点
        vector<int>pre_left,pre_right,vin_left,vin_right;
        
        //寻找标志位(中间位置节点)
        int flag = 0;
        for(int i = 0; i < len; i++){
            if(vin[i] == pre[0])
                flag = i;
        }
        
        //分类
        for(int i = 0; i < len; i++){
            if(i < flag){
                pre_left.push_back(pre[i+1]);
                vin_left.push_back(vin[i]);
            }
            if(i > flag){
                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;
    }
};

 

优化改进:某大佬剑指offer的思路:https://cuijiahua.com/blog/learing-algorithm/basis/page/7/

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值