代码随想Day20 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

654.最大二叉树

 这道题和通过中序和后序序列构建二叉树的思路异曲同工,递归三步走:

1. 参数:返回TreeNode指针,传入参数,数组以及开始和结束索引;

2. 结束条件:如果数组为空,返回nullptr;如果数组只剩一个元素,说明到了叶子节点,返回即可;

3. 单层处理逻辑:(前序遍历) 首先找最大值,然后把最大值构建为根节点,根节点的左右节点再递归即可。

详细代码:

class Solution {
public:
    TreeNode* dfs(vector<int>& nums, int l, int r)
    {
        //结束条件
        if(l>=r) return nullptr;
        if(r-l==1)
        {
            TreeNode* root = new TreeNode(nums[l]);
            return root;
        }
        //找最大值
        int max_index;
        int max_value = INT_MIN;
        for(int i=l;i<r;i++)
        {
            if(nums[i]>max_value)
            {
                max_value = nums[i];
                max_index = i;
            }
        }
        //分割-左闭右开
        TreeNode* root = new TreeNode(max_value);
        int l_beg = l;
        int l_end = max_index;
        int r_beg = max_index+1;
        int r_end = r;

        //递归
        root->left = dfs(nums, l_beg, l_end);
        root->right = dfs(nums,r_beg, r_end);
        return root;

    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        //if(nums.size()==0) return nullptr;
        return dfs(nums,0,nums.size());
    }
};

617.合并二叉树

这道题使用前序遍历,中左右即可,我写的错误代码如下:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1==nullptr&&root2==nullptr) return nullptr;
        //中
        TreeNode* root = new TreeNode(0);
        if(root1==nullptr) root->val = root2->val;
        else if(root2==nullptr) root->val = root1->val;
        else{ 
            root->val =root1->val+root2->val;
            root->left = mergeTrees(root1->left, root2->left);
            root->right = mergeTrees(root1->right, root2->right);
            return root;
        }


    }
};

debug发现这种思路的错误之处在于,当其中一个节点为空时,这个时候只是把另一个root的值给了新的节点,但是另一个root的子节点并不会随之复制,这样会导致新树的节点缺失,正确的思路应该是返回另一个root的指针,而不是单纯的值复制,修改后可以运行的代码如下:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1==nullptr&&root2==nullptr) return nullptr;
        //中
        TreeNode* root = new TreeNode(0);
        if(root1==nullptr) //root->val = root2->val;
            return root2;
        else if(root2==nullptr) //root->val = root1->val;
            return root1;
        else{ 
            root->val =root1->val+root2->val;
            root->left = mergeTrees(root1->left, root2->left);
            root->right = mergeTrees(root1->right, root2->right);
            return root;
        }


    }
};

但是这个代码不简洁易懂,看了代码随想录之后精炼代码如下:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1==nullptr) return root2;
        if(root2==nullptr) return root1;
        TreeNode* root = new TreeNode(0); 
        root->val =root1->val+root2->val;//中
        root->left = mergeTrees(root1->left, root2->left); //左
        root->right = mergeTrees(root1->right, root2->right); //右
        return root;
    }
};

700.二叉搜索树中的搜索

这道题考察的是二叉搜索树的性质,二叉搜索树中左子树所有元素小于根节点小于右子树,同时左右子树也满足上述,本质上来说,如果把二叉搜索树的中序遍历打印出来,就是一个递增的序列。因此这道题,直接使用该性质作答,代码如下:

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

    }
};

学习代码随想录的递归写法:

1. 确定递归函数的参数和返回值

递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。

2. 确定终止条件

如果root为空,或者找到这个数值了,就返回root节点。

3. 确定单层递归的逻辑

看看二叉搜索树的单层递归逻辑有何不同。

因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。

如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。

详细代码如下:

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root==nullptr|| root->val==val) return root;
        if(root->val>val) return searchBST(root->left, val);
        if(root->val<val) return searchBST(root->right, val);
        return nullptr; //都没找到,返回nullptr
    }
};

98.验证二叉搜索树 

递归写法:需要维护一个pre指针来代表中序遍历的前一个节点,两者比较大小,用中序遍历来完成这道题,详细代码如下:

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:
    bool isValidBST(TreeNode* root) {
        //迭代写法
        TreeNode* pre = nullptr;
        TreeNode* cur = root;
        stack<TreeNode*> s;
        while(cur!=nullptr||!s.empty())
        {
            if(cur)
            {
                s.push(cur);
                cur=cur->left;
            }
            else
            {
                cur = s.top();
                s.pop();
                if(pre!=nullptr&&pre->val>=cur->val) return false; //比较
                pre = cur; //更新pre
                cur = cur->right;
            }
        }
        return true;

    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值