leetcode 98验证二叉搜索树

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int>nums;
    vector<int> inorder(TreeNode *root){
        if(root == nullptr){
            return nums;
        }
        inorder(root->left);
        nums.push_back(root->val);
        inorder(root->right);
        return nums;
    }
    bool isValidBST(TreeNode* root) {
        vector<int>res;
        res = inorder(root);
        for(int i = 1;i<res.size();i++){
            if(res[i]<=res[i-1]){
                return false;
            }
        }
        return true;
    }
};
cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 * };
 */

class Solution {
public:

    // helper函数作用:
    // 判断以root为根节点的树是否满足BST条件
    //
    // lower:当前节点允许的最小值
    // upper:当前节点允许的最大值
    //
    // 当前节点必须满足:
    // lower < root->val < upper
    bool helper(TreeNode* root, long long lower, long long upper) {


        // 1. 递归终止条件
        //
        // 空节点不违反BST规则
        // 所以返回true
        if(root == nullptr){
            return true;
        }


        // 2. 判断当前节点是否合法
        //
        // BST要求:
        // 当前节点必须严格大于lower
        // 且严格小于upper
        //
        // 如果超出范围,说明不是BST
        if(root->val <= lower || root->val >= upper){
            return false;
        }


        // 3. 递归检查左子树
        //
        // 左子树所有节点都必须小于当前节点
        //
        // 所以:
        // 上界变成当前节点值
        //
        // 原范围:
        // (lower, upper)
        //
        // 左子树范围:
        // (lower, root->val)
        bool left = helper(root->left, lower, root->val);



        // 4. 递归检查右子树
        //
        // 右子树所有节点都必须大于当前节点
        //
        // 所以:
        // 下界变成当前节点值
        //
        // 右子树范围:
        // (root->val, upper)
        bool right = helper(root->right, root->val, upper);



        // 5. 左右子树都满足BST条件
        // 当前树才是BST
        return left && right;
    }



    bool isValidBST(TreeNode* root) {

        // 根节点一开始没有限制
        // 所以给一个最大范围
        return helper(root, LONG_MIN, LONG_MAX);
    }
};

递归思路总结

这道题的核心不是比较:

复制代码
root->left < root
root->right > root

因为这样只能判断直接孩子。

例如:

复制代码
        5
       / \
      3   8
         /
        4

看起来:

复制代码
4 < 8

好像满足。

但是 4 在 5 的右子树中。

BST要求:

复制代码
右子树所有节点 > 5

而:

复制代码
4 < 5

所以错误。


上下界递归的核心

进入每一层递归,都给当前节点一个合法范围。

比如:

复制代码
        8
       / \
      3   10
     /
    1

开始:

复制代码
8的范围:

(-∞, +∞)

检查左孩子3:

因为3在8左边:

复制代码
3必须满足:

-∞ < 3 < 8

所以递归:

复制代码
helper(3, LONG_MIN, 8)

检查1:

因为1在3左边:

范围继续缩小:

复制代码
-∞ < 1 < 3

所以:

复制代码
helper(1, LONG_MIN, 3)

你会发现:

递归过程中,范围越来越严格。


递归模板

以后遇到类似树的递归,可以套:

复制代码
返回值 dfs(节点, 当前限制){

    // 1. 终止条件
    if(节点为空){
        return 初始结果;
    }


    // 2. 当前节点处理


    // 3. 递归处理子树


    // 4. 合并子树结果


    return 结果;
}

这题:

复制代码
dfs(root, lower, upper)

代表:

判断当前节点是否在合法范围内,并继续检查左右子树。


这道题记忆重点

记住三句话:

① BST性质

复制代码
左子树所有节点 < 根节点 < 右子树所有节点

② 递归传递范围

左子树:

复制代码
helper(root->left, lower, root->val)

因为:

复制代码
左边最大不能超过当前节点

右子树:

复制代码
helper(root->right, root->val, upper)

因为:

复制代码
右边最小不能低于当前节点

③ 递归思想

不要想着:

我要把整棵树全部检查完。

而是:

我相信 helper 可以检查好左右子树,我只需要检查当前节点,并把正确范围传下去。

这就是递归在二叉树问题中的核心思想。

相关推荐
朝朝辞暮i9 分钟前
C++ 第 31C 课:Subscriber 到底是什么
开发语言·c++·算法
杨逢昌工厂6S管理24 分钟前
109-杨逢昌车间管理负熵循环:三环体系持续输出负熵的机制解析
经验分享·笔记·职场和发展·学习方法
Evand J42 分钟前
【MATLAB例程】三维RRT+APF路径规划与AOA-TDOA融合定位算法。附代码的下载链接
算法·matlab·路径规划·rrt·tdoa·apf·aoa
海绵宝宝转agent1 小时前
leetCode100算法开源笔记分享
笔记·算法
写后端的胖头鱼2 小时前
时间复杂度 & 空间复杂度
java·数据结构·算法·时间复杂度·空间复杂度
hahaha60162 小时前
黑体轨迹和色温--光源白点
人工智能·嵌入式硬件·算法·计算机视觉
海绵宝宝转agent2 小时前
基于Redis ZSet+AOP+注解实现限流注解算法
数据库·redis·算法
All for pursuit.3 小时前
【回溯-7】494.目标和
数据结构·c++·算法·leetcode
白杨尚青3 小时前
C++入门篇(十三):vector(上)——动态数组:构造、空间增长与迭代器失效
开发语言·c++·笔记·算法·stl
Jasmine_llq3 小时前
《P17461 [GESP202609 八级] 生成树计数》
算法·栈·tarjan 算法·边双连通分量·深度优先搜索 dfs·tarjan 保存当前路径节点·模乘法