LeetCode98:验证二叉搜索树(多解)

题目LeetCode98

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含严格小于当前节点的数。
  • 节点的右子树只包含 严格大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树

示例

**输入:**root = 2,1,3

**输出:**true

Python解法

解法一(递归)

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        # 辅助函数:检查以node为根的子树是否在(low, high)这个区间内
        def check(node, must_greater_than, must_less_than):
            # 情况1:节点是空的,说明这条路径没问题,返回True
            if not node:
                return True
            
            # 情况2:节点不满足"必须大于左边的数"
            if must_greater_than is not None and node.val <= must_greater_than:
                return False
            
            # 情况3:节点不满足"必须小于右边的数"
            if must_less_than is not None and node.val >= must_less_than:
                return False
            
            # 检查左子树:
            #  左子树所有节点都必须 < 当前节点值
            #  同时左子树所有节点都要继承"必须大于的数"
            left_ok = check(node.left, must_greater_than, node.val)
            
            # 检查右子树:
            #  右子树所有节点都必须 > 当前节点值
            #  同时右子树所有节点都要继承"必须小于的数"
            right_ok = check(node.right, node.val, must_less_than)
            
            # 左右都没问题,整棵子树才是合法的
            return left_ok and right_ok
        
        # 根节点一开始没有任何限制:
        #  没有"必须大于谁",也没有"必须小于谁"
        return check(root, None, None)

解法二(中序遍历)

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isValidBST(self, root: Optional[TreeNode]) -> bool:
        stack = []
        prev = float('-inf')  # 记录中序遍历的前一个节点值

        # 中序遍历的标准迭代写法:左-根-右
        while stack or root:
            # 1. 一路往左走,把所有左节点压入栈
            while root:
                stack.append(root)
                root = root.left
            
            # 2. 取出栈顶节点(此时是当前最左未访问的节点)
            root = stack.pop()

            # 3. 核心判断:当前节点值必须严格大于前一个节点值
            if root.val <= prev:
                return False
            prev = root.val  # 更新前一个节点值为当前值

            # 4. 转向右子树(下一轮继续处理右子树的左分支)
            root = root.right
        
        return True

过程展示

Java解法

解法一(递归)

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        return check(root, null, null);
    }

    /**
     * @param node 当前要检查的节点
     * @param mustGreaterThan 当前节点必须大于这个值(可以为 null,表示无下限)
     * @param mustLessThan 当前节点必须小于这个值(可以为 null,表示无上限)
     */
    private boolean check(TreeNode node, Integer mustGreaterThan, Integer mustLessThan) {
        // 空节点默认合法
        if (node == null) {
            return true;
        }

        // 不满足下限限制
        if (mustGreaterThan != null && node.val <= mustGreaterThan) {
            return false;
        }
        // 不满足上限限制
        if (mustLessThan != null && node.val >= mustLessThan) {
            return false;
        }

        // 左子树:上限变成当前节点值,下限继承
        boolean leftOk = check(node.left, mustGreaterThan, node.val);
        // 右子树:下限变成当前节点值,上限继承
        boolean rightOk = check(node.right, node.val, mustLessThan);

        return leftOk && rightOk;
    }
}

解法二(中序遍历)

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        long prev = Long.MIN_VALUE; // 用 long 避免 int 边界溢出

        while (!stack.isEmpty() || root != null) {
            // 一路向左走,全部入栈
            while (root != null) {
                stack.push(root);
                root = root.left;
            }

            // 弹出节点
            root = stack.pop();

            // 核心判断:必须严格递增
            if (root.val <= prev) {
                return false;
            }
            prev = root.val;

            // 走向右子树
            root = root.right;
        }
        return true;
    }
}

C++解法

解法一(递归)

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:
    bool isValidBST(TreeNode* root) {
        return check(root, nullptr, nullptr);
    }

private:
    /**
     * @param node 当前节点
     * @param mustGreaterThan 当前节点必须大于这个值(可以为 nullptr,表示无下限)
     * @param mustLessThan 当前节点必须小于这个值(可以为 nullptr,表示无上限)
     */
    bool check(TreeNode* node, int* mustGreaterThan, int* mustLessThan) {
        if (!node) {
            return true;
        }

        // 不满足下限限制
        if (mustGreaterThan != nullptr && node->val <= *mustGreaterThan) {
            return false;
        }
        // 不满足上限限制
        if (mustLessThan != nullptr && node->val >= *mustLessThan) {
            return false;
        }

        // 左子树:上限变成当前节点值,下限继承
        bool leftOk = check(node->left, mustGreaterThan, &(node->val));
        // 右子树:下限变成当前节点值,上限继承
        bool rightOk = check(node->right, &(node->val), mustLessThan);

        return leftOk && rightOk;
    }
};

解法二(中序遍历)

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:
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> stack;
        long prev = LONG_MIN; // 避免 int 边界问题

        while (!stack.empty() || root != nullptr) {
            // 一路向左走,全部入栈
            while (root != nullptr) {
                stack.push(root);
                root = root->left;
            }

            // 弹出节点
            root = stack.top();
            stack.pop();

            // 核心判断
            if (root->val <= prev) {
                return false;
            }
            prev = root->val;

            // 走向右子树
            root = root->right;
        }
        return true;
    }
};
相关推荐
金幄科技几秒前
RAG第四篇:重排序 Rerank——粗召回之后,为什么还需要一次精排
人工智能·算法·ai·ai编程
青 春 记 忆3 分钟前
零基础入门python25:新增账目——Decimal、日期和输入校验
python·后端开发
北风toto4 分钟前
阿里云 MaxCompute通过python脚本调用odps流程和执行sql
python·阿里云·odps
M78佐菲6 分钟前
Linux学习笔记:文件IO
linux·笔记·学习·算法
ShineWinsu9 分钟前
对于TRAE中配置Qt的解析
开发语言·c++·ide·vscode·qt·ai·trae
谢亮_vipxieliang10 分钟前
手机号验证技术方案:号段规则与正则表达式
java·服务器·spring boot·正则表达式·hibernate
qq_1611112721 分钟前
Pillow项目深度解析:Python图像处理的终极武器
图像处理·python·pillow·开源库·历史解析
wang090722 分钟前
自己动手写一个tomcat之7监听器和过滤器
java·tomcat
梅孔立22 分钟前
Pi-Agent 终极极简配置文档(Java+Vue+Python爬虫 4-5千文件项目)
java·vue.js·python
李可以量化27 分钟前
Redis Client 从了解到精通(二)下:String 类型进阶操作全解
redis·git·python·量化交易·qmt