98. Validate Binary Search Tree

js
var isValidBST = function (root) {
// 初始化前驱节点的值为负无穷,用于记录中序遍历的上一个节点值
// 选择负无穷是因为二叉树节点值可能包含任意整数(包括极小值)
let pre = -Infinity
/**
* 深度优先搜索(DFS)的递归函数,执行中序遍历并验证升序特性
* @param {TreeNode} node - 当前遍历的节点
* @returns {boolean} - 当前子树是否满足BST条件
*/
function dfs(node) {
// 递归终止条件:遇到空节点,空树/空子树默认是有效的BST
if (node == null) {
return true
}
// 1. 遍历左子树(中序遍历:左)
// 如果左子树不满足BST条件,直接返回false,无需继续遍历
if (!dfs(node.left)) {
return false
}
// 2. 处理当前节点(中序遍历:中)
// 核心验证逻辑:BST要求当前节点值必须严格大于前驱节点值
// 若当前节点值 <= 前驱节点值,说明不满足BST特性,返回false
if (node.val <= pre) {
return false
}
// 更新前驱节点值为当前节点值,供后续右子树验证使用
pre = node.val
// 3. 遍历右子树(中序遍历:右)
// 右子树的验证结果直接返回(若右子树不满足,整体就不满足)
return dfs(node.right)
}
// 从根节点开始执行中序遍历验证
return dfs(root)
}举个反例
考虑下面这棵树:
text
10
/ \
5 15
/ \
6 20- 按你的代码逻辑:
- 在根节点 10 处,5<10 且 15>10 ✅,再分别递归检查子树;
- 对子树根 15,6<15 且 20>15 ✅,再递归检查它们都是叶子也都返回 True;
- 整棵树被判作合法 BST。
- 但实际上,节点 6 在 10 的右子树中,却 6<10,违背了 BST 要求“右子树所有节点都 > 10”的规则。
正确思路
要验证一棵树是不是 BST,必须对每个节点维护一个上下界(lower < node.val < upper):
python
def isValidBST(root):
def helper(node, lower, upper):
if not node:
return True
val = node.val
# 如果超出允许区间,立刻 False
if val <= lower or val >= upper:
return False
# 左子树所有节点必须 < val;右子树所有节点必须 > val
return helper(node.left, lower, val) and \
helper(node.right, val, upper)
# 整棵树任意值都要在 (-∞, +∞) 之间
return helper(root, float('-inf'), float('inf'))这样,访问到节点 6 时,它所在的调用栈里 lower=10、upper=15,会被马上判为 False。
另一种简洁做法:中序遍历
因为 BST 的 中序遍历结果一定是一个严格递增的序列,我们也可以这样写:
python
def isValidBST(root):
prev = float('-inf')
def inorder(node):
nonlocal prev
if not node:
return True
if not inorder(node.left):
return False
# 这里要严格大于前一个值
if node.val <= prev:
return False
prev = node.val
return inorder(node.right)
return inorder(root)这两种方法都能正确处理“深层子孙节点违反祖先约束”的情况,你可以根据习惯任选其一。
二叉搜索树

前序遍历(preorder traversal)
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], left=-inf, right=inf) -> bool:
if not root:
return True
x = root.val
return left < x < right and self.isValidBST(root.left, left, x) and self.isValidBST(root.right, x, right)先访问节点,再遍历左右子树
思路:给isValidBST 加上left和right两个参数,二叉搜索树的左子树区间在(left, x.val) 之间,右子树同理。
中序遍历(inorder)
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:
pre = -inf
def isValidBST(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
# check left child
if not self.isValidBST(root.left):
return False
# 不能写成 val > self.pre return Ture
# 不然会直接返回True
if root.val <= self.pre:
return False
self.pre = root.val
return self.isValidBST(root.right)后序遍历(postorder)
