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;
    }
};
相关推荐
千寻girling1 小时前
周日那天参加的力扣周赛... —— 10号
java·javascript·c++·python·算法·leetcode·职场和发展
guygg881 小时前
基于 DWT 的盲数字水印实现(嵌入与提取)
算法
TechWayfarer1 小时前
订单未到、运力先行:IP精确地理位置在物流调度中的实战应用
服务器·网络·python·tcp/ip·交通物流
凛_Lin~~1 小时前
lifecycle源码解析 (版本2.5.1)
android·java·安卓·lifecycle
故事还在继续吗1 小时前
嵌入式 C 语言程序性能优化
c语言·开发语言·性能优化
鱼子星_1 小时前
最短路问题【图论】
数据结构·算法·贪心算法·动态规划·图论
Devin~Y1 小时前
大厂Java面试实录:Spring Boot微服务 + Redis/Kafka + Prometheus/Jaeger + RAG/Agent(小Y水货版)
java·spring boot·redis·spring cloud·kafka·prometheus·jaeger
zhoumeina991 小时前
设计器模版底图,一直渲染错误,是因为第一张图变形后内存中图片数据被改了,其他尺码一直错误
java·前端·javascript
Mike117.1 小时前
GBase 8c 会话、锁等待和长 SQL 的日常巡检写法
java·数据库·sql