LeetCode刷题笔记【14】:二叉树专题-6(最大二叉树 、合并二叉树 、二叉搜索树中的搜索 、验证二叉搜索树)

前置知识

参考前文

参考文章:
LeetCode刷题笔记【9】:二叉树专题-1(分别用递归遍历、迭代遍历、标记遍历实现前、中、后序遍历)
LeetCode刷题笔记【10】:二叉树专题-2(二叉树的层序遍历、翻转二叉树、对称二叉树)
LeetCode刷题笔记【10.5】:二叉树专题-2.5(二叉树的层序遍历 - 10道题)
LeetCode刷题笔记【11】:二叉树专题-3(二叉树的最大深度、二叉树的最小深度、完全二叉树的节点个数)
LeetCode刷题笔记【12】:二叉树专题-4(平衡二叉树、二叉树的所有路径、左叶子之和)
LeetCode刷题笔记【13】:二叉树专题-5(找树左下角的值 、路径总和、从前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树)

654.最大二叉树

题目描述

在这里插入图片描述
在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/maximum-binary-tree/description/

递归法

思路: 创建辅助递归函数, 用left和right表示子串的左右坐标, 先选其中最大, 再递归调用传入左右子串儿

class Solution {
public:
    TreeNode* build(vector<int>& nums, int left, int right){
        if(nums.size()==0 || left>right){
            return nullptr;
        }
        int position, maxNum=INT_MIN;
        for(int i=left; i<=right; ++i){
            if(nums[i]>maxNum){
                maxNum = nums[i];
                position = i;
            }
        }
        TreeNode* node = new TreeNode(maxNum);
        node->left = build(nums, left, position-1);
        node->right = build(nums, position+1, right);
        return node;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return build(nums, 0, nums.size()-1);
    }
};

遍历 + 单调栈

上一种方法中对于每个子串都需要遍历找最大值, 时间复杂度是O(n^2)
只遍历一次数组(时间复杂度O(n), 在过程中维护一个单调栈(栈顶为小, 栈底为大)
对于数组中当前遍历的数字k
① 新建val=k的节点node
② 如果k>top, 就pop, 并且在pop的过程中不断让node->left = top
③ 如果②后栈不为空, 则top->right = node
st.push(node)
⑤ 遍历完nums以后, 返回栈底元素

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        stack<TreeNode*> st;
        for(int k : nums){
            TreeNode* node = new TreeNode(k);
            while(!st.empty() && k>st.top()->val){
                node->left = st.top();
                st.pop();
            }
            if(!st.empty()){
                st.top()->right = node;
            }
            st.push(node);
        }
        TreeNode* ans;
        while(!st.empty()){
            ans = st.top();
            st.pop();
        }
        return ans;
    }
};

这个题解讲的很好: https://leetcode.cn/problems/maximum-binary-tree/solutions/1762756/letmefly-shi-pin-yan-shi-654zui-da-er-ch-2fcl/

617.合并二叉树

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/merge-two-binary-trees/description/

解题思路

其实也是遍历, 但是对每个遍历节点的操作有所不同

代码

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        TreeNode* ans;
        if(root1==nullptr)  return root2;
        if(root2==nullptr)  return root1;
        ans = root1;
        ans->val += root2->val;
        ans->left = mergeTrees(root1->left, root2->left);
        ans->right = mergeTrees(root1->right, root2->right);
        return ans;
    }
};

700.二叉搜索树中的搜索

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/search-in-a-binary-search-tree/description/

解题思路

思路: 根据二叉搜索树的性质进行定向查找
cur->val < val: 向右侧查找
cur->val > val: 向左侧查找

代码

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

98.验证二叉搜索树

题目描述

在这里插入图片描述

LeetCode链接:https://leetcode.cn/problems/validate-binary-search-tree/description/

错误思路(坑)

思路: 进行遍历, 检测curNode->val是否在curNode->left->valcurNode->right->val之间

// class Solution {
// public:
//     bool isValidBST(TreeNode* root) {
//         if(root==nullptr)
//             return true;
//         if(root->left && root->val <= root->left->val){
//             return false;
//         }
//         if(root->right && root->val >= root->right->val){
//             return false;
//         }
//         return isValidBST(root->left) && isValidBST(root->right);
//     }
// };

递归传递合法范围, 检测当前节点是否合法

以上方法只检测一层的大小关系, 无法进行更远关系的检测, 比如**[5,4,6,null,null,3,7]**
所以需要一路传过来更远的关系

class Solution {
public:
    bool check(TreeNode* root, long long minNum, long long maxNum){
        if(root==nullptr)
            return true;
        if(root->val <= minNum || root->val >= maxNum)
            return false;
        return check(root->left, minNum, root->val) && check(root->right, root->val, maxNum);
    }
    bool isValidBST(TreeNode* root) {
        return check(root, LONG_MIN, LONG_MAX);
    }
};

遍历得到中序遍历序列, 检测是否递增

可以在过程中比较, 也可以先一整个遍历结束再比较;
那就是遍历生成整个树的中序遍历, 然后再check

class Solution {
public:
    void traversal(TreeNode* root, vector<long long>& marker){
        if(root==nullptr)
            return;
        if(root->left)
            traversal(root->left, marker);
        marker.push_back(root->val);
        if(root->right)
            traversal(root->right, marker);
        return;
    }
    bool isValidBST(TreeNode* root) {
        vector<long long> marker;
        traversal(root, marker);
        // return is_sorted(marker.begin(), marker.end());
        // 这里没法用is_sorted, 因为它检测的升序是不严格升序, 包括=的情况, 还得是要自己写
        if(marker.size()==0 || marker.size()==1)
            return true;
        for(int i=0; i<marker.size()-1; ++i){
            if(marker[i]>=marker[i+1])
                return false;
        }
        return true;
    }
};

本文参考:
最大二叉树
合并二叉树
二叉搜索树中的搜索
验证二叉搜索树

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值