98.Validate_Binary_Search_Tree

25 年 7 月 2 日 星期三
756 字
4 分钟

98. Validate Binary Search Tree

My Solution:

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:
        if not root:
            return True
        if root.left is None and root.right is None:
            return True
        if root.left is None:
            return root.right.val > root.val and self.isValidBST(root.right)
        if root.right is None:
            return root.left.val < root.val and self.isValidBST(root.left)
        return root.left.val < root.val and root.right.val > root.val and \
        self.isValidBST(root.left) and self.isValidBST(root.right)

问题

这个写法的根本问题在于,它只检查了每个节点的直接左右子节点值关系,却没有把“整个左子树的值都要<当前节点”与“整个右子树的值都要>当前节点”这两个全局约束纳入考量。


举个反例

考虑下面这棵树:

text
      10
     /  \
    5    15
        /  \
       6    20
  • 按你的代码逻辑:
    1. 在根节点 10 处,5<10 且 15>10 ✅,再分别递归检查子树;
    2. 对子树根 15,6<15 且 20>15 ✅,再递归检查它们都是叶子也都返回 True;
    3. 整棵树被判作合法 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=10upper=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)

这两种方法都能正确处理“深层子孙节点违反祖先约束”的情况,你可以根据习惯任选其一。

二叉搜索树

image-20250702225743958

前序遍历(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)

image-20250703170847485

文章标题:98.Validate_Binary_Search_Tree

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/98validate_binary_search_tree[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。