day-20 代码随想录算法训练营(19)二叉树part06 已二刷

文章详细探讨了最大二叉树构造、切割数组与指针操作、二叉搜索树功能实现、合并二叉树、搜索算法以及二叉树到累加树的转换,展示了丰富的算法应用场景。
摘要由CSDN通过智能技术生成

654.最大二叉树

思路一:切割数组,生成新的左右数组
思路二:使用指针直接操作
class Solution {
public:
    TreeNode*judge(vector<int>&nums,int left,int right){
        if(left>=right) return nullptr;
        //分割点下标
        int maxNum=nums[left],index=left;//maxNum初始值为区间最左边的数
        for(int i=left+1;i<right;i++){//获取最大值和下标
            if(nums[i]>maxNum){
                maxNum=nums[i];
                index=i;
            }
               
        }
        //cout<<index;
        TreeNode*root=new TreeNode(maxNum);
        //切割左子树和右子树
        // vector<int> leftNums(nums.begin(),nums.begin()+index);
        // vector<int> rightNums(nums.begin()+index+1,nums.end());
        root->left=judge(nums,left,index);
        root->right=judge(nums,index+1,right);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        //思路二:不进行切割,直接在原数组上进行操作
        return judge(nums,0,nums.size());
    }
};
 二刷:
思路一:切割数组
class Solution {
public:
    TreeNode*containTree(vector<int>&nums){
        if(nums.size()==0) return nullptr;
        int maxValue=0,maxIndex=0;
        for(int i=0;i<nums.size();i++){
            if(nums[i]>maxValue){
                maxValue=nums[i];
                maxIndex=i;
            }
        }
        TreeNode*root=new TreeNode(maxValue);
        vector<int>leftnums(nums.begin(),nums.begin()+maxIndex);
        vector<int>rightnums(nums.begin()+maxIndex+1,nums.end());
        root->left=containTree(leftnums);
        root->right=containTree(rightnums);
        return root;

    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return containTree(nums);
    }
};
思路二:双指针操作
class Solution {
public:
    TreeNode*containsTree(vector<int>&nums,int left,int right){
        if(left>=right) return nullptr; 
        int maxValue=nums[left],maxIndex=left;//因为存在 0 值,所以初始化为最左边的数
        for(int i=left+1;i<right;i++){        //可以避免只有0值的情况导致 maxIndxe 为0
            if(nums[i]>maxValue){
                maxValue=nums[i];
                maxIndex=i;
            }
        }
        TreeNode*root=new TreeNode(maxValue);
        root->left=containsTree(nums,left,maxIndex);
        root->right=containsTree(nums,maxIndex+1,right);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return containsTree(nums,0,nums.size());
    }
};

617.合并二叉树

思路一:创建新的二叉树
思路二:直接在二叉树上操作
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        //思路:直接同时遍历两个二叉树,子节点不存在传入下一个为空指针
        if(root1==nullptr) return root2;
        if(root2==nullptr) return root1;
        root1->val+=root2->val;
        root1->left=mergeTrees(root1->left,root2->left);
        root1->right=mergeTrees(root1->right,root2->right);
        return root1;

    }
};
 二刷路过

700.二叉树中的搜索

思路:利用二叉搜索树的特性

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        //思路:找到节点,然后返回
        //分析:左子节点比父节点小,右子节点比父节点大
        if(root==nullptr)
            return root;
        TreeNode*newNode=root;;
        if(newNode->val>val)
            newNode=searchBST(newNode->left,val);
        else if(newNode->val<val)
            newNode=searchBST(newNode->right,val);
        return newNode;
    }
};

 二刷:

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root==nullptr) return nullptr;
        else if(root->val==val) return root;
        else if(root->val>val) return searchBST(root->left,val);
        return searchBST(root->right,val);
    }
};

98.验证二叉搜索树

思路一:利用二叉搜索树的特性,中序遍历的数组必为升序
class Solution {
public:
    vector<int>ans;
    void judge(TreeNode*root){
        if(root==nullptr) return;
        judge(root->left);
        ans.push_back(root->val);
        judge(root->right);
    }
    bool isValidBST(TreeNode* root) {
        //思路:直接分析
        //思路二:中序遍历的数组一定递增
        judge(root);
        if(ans.size()==1) return true;
        int pre=ans[0];
        for(int i=1;i<ans.size();i++){
            if(ans[i]<=pre)
                return false;
            pre=ans[i];
        }
        return true;
    }
};
思路二:在递归的过程中直接判断,采用中序遍历,每次都记录上一个节点,然后判断当前节点是否大于上一个节点
class Solution {
public:
    TreeNode*pre=nullptr;
    bool isValidBST(TreeNode* root) {
        if(root==nullptr) return true;//空树也是二叉搜索树
        bool left=isValidBST(root->left);

        if(pre!=nullptr && pre->val>=root->val) return false;//判断上一个节点是否小于当前节点
        pre=root;

        bool right=isValidBST(root->right);
        return left && right; 
        
    }
};

二刷:

class Solution {
public:
    vector<int>mid;
    int count=0;//计数
    void judge(TreeNode*root){//中序遍历
        if(root==nullptr) return;
        judge(root->left);
        count++;
        if(mid.empty() || root->val>mid.back()) mid.push_back(root->val);//递增时才加入
        judge(root->right);
    }
    bool isValidBST(TreeNode* root) {//中序遍历必然是递增序列
        judge(root);
        return mid.size()==count;
    }
};

669.修剪二叉搜索树

分析:分情况讨论,伪代码实现成代码,嗖嗖的
思路一:分析三种情况
           1.当前节点值在中间区间上(此时递归分析左右子节点)
           2.当前节点值在区间左边(此时当前节点不作为结果值,但右子节点中可能存在结果值,故返回分析右子节点)
           3.当前节点值在区间右边(同理,当前节点不作为结果值,但左子节点可能存在结果值,故返回分析左子节点)
注意:判断当前节点为空时返回nullptr,可以解决叶子节点问题,也可以解决当前节点等于row或者等于high的问题。
class Solution {
public:
    TreeNode*judgeNode(TreeNode*root,int low,int high){
        if(root==nullptr) return root;
        //分五种情况
        TreeNode*left,*right;
        if(root->val<low)//左边的必然不在区间内
            return judgeNode(root->right,low,high);
        else if(root->val>=low && root->val<=high){//左右两边都有可能在区间内
            left=judgeNode(root->left,low,high);
            right=judgeNode(root->right,low,high);
        }
        else if(root->val>high){
            return judgeNode(root->left,low,high);
        }
        root->left=left;
        root->right=right;
        return root;
        
    }
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        //思路:首先考虑当前中间节点有三种情况,在low左边,在high右边
        return judgeNode(root,low,high);
    }
};
二刷:
思路二:递归
class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if(root==nullptr) return nullptr;
        if(root->val<low) return trimBST(root->right,low,high);//从右子节点寻找
        if(root->val>high) return trimBST(root->left,low,high);//从左子节点寻找
        root->left=trimBST(root->left,low,high);//接住左子节点
        root->right=trimBST(root->right,low,high);//接住右子节点
        return root;//在区间内时依然返回子节点
    }
};

108.将有序数组转换为二叉搜索树

思路一:使用两个指针分割区间,每次都选择中间的值作为根节点,然后向两边切割
class Solution {
public:
    TreeNode*judge(vector<int>&nums,int left,int right){
       if(left>right) return nullptr;
       //每次都选择区间中间的数作为根节点
       int mid=(left+right)/2;
       TreeNode*root=new TreeNode(nums[mid]);
       root->left=judge(nums,left,mid-1);
       root->right=judge(nums,mid+1,right);
       return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        //思路一:高度平衡,递归切割
        //后序遍历
        return judge(nums,0,nums.size()-1);
    }
};
分析:思路是这样,但是想复杂了,直接搞得分割区间,导致越来越乱
二刷路过:
class Solution {
public:
    TreeNode*connectNode(vector<int>&nums,int left,int right){
        if(left>right) return nullptr;//因为右边界取n-1,所以 left==right 在结果中
        int index=left+(right-left)/2;
        TreeNode*root=new TreeNode(nums[index]);
        root->left=connectNode(nums,left,index-1);
        root->right=connectNode(nums,index+1,right);
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return connectNode(nums,0,nums.size()-1);
    }
};

538.把二叉搜索树转换为累加树

思路:遍历顺序为右中左,然后累加赋值
class Solution {
public:
    int sum=0;
    TreeNode* convertBST(TreeNode* root) {
        //思路:遍历顺序为右中左,然后累加赋值
        if(root!=nullptr){
            convertBST(root->right);
            sum+=root->val;
            root->val=sum;
            convertBST(root->left);
        }
        return root;
    }
};
二刷:
class Solution {
public:
    int sum=0;
    TreeNode* convertBST(TreeNode* root) {
        if(root==nullptr) return nullptr;
        convertBST(root->right);//直接往右遍历
        sum+=root->val;//累加右子节点
        root->val=sum;//赋值
        convertBST(root->left);//进入左子节点
        return root;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值