三种思路彻底掌握 BST 判断(递归与迭代全解析)——力扣98.验证二叉搜索树

力扣98.验证二叉搜索树


一、题目描述

给定一个二叉树的根节点 root,判断它是否是一棵有效的二叉搜索树(BST)。

有效二叉搜索树的定义:

  1. 节点的左子树只包含严格小于当前节点的值;
  2. 节点的右子树只包含严格大于当前节点的值;
  3. 所有左子树和右子树本身也必须是二叉搜索树。

示例 1:

复制代码
输入:root = [2,1,3]
输出:true

示例 2:

复制代码
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5,但其右子树中的节点 4 小于 5。

提示:

  • 节点总数范围:[1, 10⁴]
  • 节点值范围:[-2³¹, 2³¹ - 1]

二、思路分析

判断是否为二叉搜索树,本质上有两种思路:

  1. 区间递归法: 每个节点的值必须在一个动态变化的 (min, max) 范围内;
  2. 中序遍历法: 二叉搜索树的中序遍历序列应严格递增。

这两种思路都能达到 O(n) 的时间复杂度,区别在于递归参数设计与思维方式不同。


三、解法一:递归区间法(Top-Down)

核心思想:

从根节点开始,为每个节点维护一个允许取值的上下界:

  • 对左子树而言,最大值应为当前节点值;
  • 对右子树而言,最小值应为当前节点值。

若某个节点值不在范围内,则立即返回 false

代码实现:

java 复制代码
class Solution {
    public boolean isValidBST(TreeNode root) {
        return validate(root, Long.MIN_VALUE, Long.MAX_VALUE);
    }

    private boolean validate(TreeNode node, long min, long max) {
        if (node == null) return true;
        if (node.val <= min || node.val >= max) return false;
        return validate(node.left, min, node.val) 
            && validate(node.right, node.val, max);
    }
}

复杂度分析:

  • 时间复杂度:O(n),每个节点访问一次;
  • 空间复杂度:O(h),h 为树的高度(最坏 O(n))。

思维亮点:

  • 使用 long 避免边界越界;
  • "上下界随递归动态变化"的设计思路极具通用性。

四、解法二:中序遍历法(Inorder Traversal)

核心思想:

二叉搜索树的中序遍历结果是一个严格递增序列

因此,只需在遍历过程中比较当前节点值是否大于前一个节点值即可。

代码实现:

java 复制代码
class Solution {
    private long prev = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {
        if (root == null) return true;
        if (!isValidBST(root.left)) return false;
        if (root.val <= prev) return false;
        prev = root.val;
        return isValidBST(root.right);
    }
}

复杂度分析:

  • 时间复杂度:O(n)
  • 空间复杂度:O(h)

思维亮点:

  • 利用 BST 的中序有序性质;
  • 实现极为简洁,逻辑清晰。

五、解法三:迭代中序法(使用显式栈)

核心思想:

用栈模拟中序遍历过程,每次取出最左节点,与前驱节点比较。

代码实现:

java 复制代码
import java.util.Stack;

class Solution {
    public boolean isValidBST(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curr = root;
        long prev = Long.MIN_VALUE;

        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            if (curr.val <= prev) return false;
            prev = curr.val;
            curr = curr.right;
        }
        return true;
    }
}

复杂度分析:

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

思维亮点:

  • 无递归调用栈;
  • 适合面试场景手写;
  • 清晰体现中序遍历过程。

六、方法对比总结

方法 思路核心 实现方式 是否递归 是否利用中序有序性 时间复杂度 空间复杂度 特点
区间递归法 动态上下界限制 递归 O(n) O(h) 思维直观、通用性强
中序递归法 严格递增序列 递归 O(n) O(h) 简洁优雅、代码最短
迭代中序法 栈模拟中序 迭代 O(n) O(n) 面试友好、结构清晰

扩展思考:

  • 若想要"找到二叉搜索树中的第 k 小节点",可以在中序遍历中计数;
  • 若想"修复错误的二叉搜索树",也可以利用中序递增特性定位错误节点。

相关推荐
吃着火锅x唱着歌5 分钟前
LeetCode 2016.增量元素之间的最大差值
数据结构·算法·leetcode
qq192572302713 分钟前
c++特性
开发语言·c++·算法
徐子童15 分钟前
FloodFill---BFS
算法·bfs·宽度优先·队列·floodfill
我命由我1234524 分钟前
Photoshop - Photoshop 工具栏(20)混合器画笔工具
经验分享·笔记·学习·ui·职场和发展·职场发展·photoshop
jerryinwuhan1 小时前
SVM案例分析
算法·机器学习·支持向量机
高山上有一只小老虎1 小时前
购物消费打折
java·算法
郝学胜-神的一滴1 小时前
计算机图形中的法线矩阵:深入理解与应用
开发语言·程序人生·线性代数·算法·机器学习·矩阵·个人开发
m0_591338912 小时前
day8鹏哥C语言--函数
c语言·开发语言·算法
_OP_CHEN2 小时前
算法基础篇:(二)基础算法之高精度:突破数据极限
算法·acm·算法竞赛·高精度算法·oj题
一只老丸2 小时前
HOT100题打卡第30天——技巧
算法