二叉树刷题系列(二)

本章leetcode题解

654.最大二叉树(难度 Medium)

105.从前序与中序遍历序列构造二叉树(难度 Medium)

106.从中序与后序遍历序列构造二叉树(难度 Medium)

上一篇讲到刷二叉树时需要注意顺序+当前节点操作。今天涉及的三道题实际上还是这么大回事,只不过递归的时候同时引入了分治,因此需要考虑一些边界。

654 最大二叉树

在这里插入图片描述
题目种给出的定义其实挺清楚了。对于一个最大二叉树的建造实际上就是。
根为树中的最大元素,并且左右子树也是最大二叉树。

OK!那么对于我们就是要找准左右部分,然后交给递给继续去构建最大二叉树就完事了。

其实还是前序遍历(对应范围)+当前操作(取此时数组的最大值)。

不过要注意边界范围,容易犯错。

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
         int size = nums.size();
         if(size == 0) return NULL;
        return constructMax(nums,0,nums.size()-1);
         
    }

    TreeNode* constructMax(vector<int>& nums,int left,int right){
        if(left>right) return NULL;
        int max=INT_MIN;
        int maxIndex;

        //找到最大数和最大小标
        for(int i = left;i<=right;i++){
             if(nums[i]>max){
                 max = nums[i];
                 maxIndex =i;
             }
         }

        //节点处理
         TreeNode* root = new TreeNode;
         root->val = nums[maxIndex];
         
         root->left = constructMax(nums,left,maxIndex-1);
         root->right =constructMax(nums,maxIndex+1,right);
         return root;
    }
    
};

105.从前序与中序遍历序列构造二叉树(难度 Medium)

OK,给出两个序列叫你构建二叉树。那自然我们要分析下这两个序列能给我们提供一些什么信息。前序遍历意味着我们能够轻松的知道对应的根节点,有了根节点就相当于找到了主心骨。这之后就是要问问左右子树怎么来。

既然我们已经知道根节点元素,即对应前序数组的第一个元素。那么我们在中序遍历中找到这个元素是不是就自然的把元素分成左右两个部分了呢?

因此,思路已经梳理出来。前序遍历提供根节点,中序遍历根据根节点能够分出左右子树的长度。剩下的当然就交给递归序列接着去做了。

还是要注意范围,不熟悉的可以画个图,或者带个值想想。
(图源:labuladong)

在这里插入图片描述
代码如下:

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
       return build(preorder,inorder,0,preorder.size()-1,0,inorder.size()-1);    
    }

    TreeNode* build(vector<int>& preorder,vector<int>& inorder,int preL,int preR,int inL,int inR){
    if(preL>preR) return NULL;

     int k; //定位根
     for(int i = inL;i<=inR;i++){
         if(preorder[preL]==inorder[i]){
             k = i;
             break;
         }
     }
     TreeNode* root = new TreeNode(preorder[preL]);
    
     root->left = build(preorder,inorder,preL+1,preL+k-inL,inL,k-1);
     root->right = build(preorder,inorder,preL+k-inL+1,preR,k+1,inR);
    return root;
    }
};

106.从中序与后序遍历序列构造二叉树(难度 Medium)

和上一题一样的思路,只需要思考好范围就能写出。

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return build(inorder,postorder,0,inorder.size()-1,0,postorder.size()-1);
    }

    TreeNode* build(vector<int>&inorder,vector<int>&postorder,int inL,int inR,int postL,int postR){
        if(postL>postR) return NULL;
        int k; //找到位置
        for(int i = inL;i<=inR;i++){
            if(postorder[postR]==inorder[i]){
                k = i;
                break;
            }
        }
        TreeNode* root = new TreeNode(postorder[postR]);
        root->left = build(inorder,postorder,inL,k-1,postL,postL+k-inL-1);
        root->right = build(inorder,postorder,k+1,inR,postL+k-inL,postR-1);
        return root;
    }

};

推荐文章

https://mp.weixin.qq.com/s/OlpaDhPDTJlQ5MJ8tsARlA

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值