返回

LeetCode 题解:判断一棵二叉树是否为二叉搜索树

前端

前言

二叉搜索树 (BST) 是一种特殊类型的二叉树,它具有以下性质:左子树中的每个节点都小于其父节点,而右子树中的每个节点都大于其父节点。判断一棵二叉树是否为 BST 是算法面试中一个常见的问题。

解法 1:递归

最直接的解法是使用递归。从根节点开始,递归地检查左子树和右子树是否为 BST。如果任一子树不是 BST,则整棵树就不是 BST。否则,我们递归地检查左子树和右子树,直到到达叶子节点。

def is_bst_recursive(root):
    if not root:
        return True

    # 检查左子树是否为 BST
    if root.left and root.val <= root.left.val:
        return False
    if is_bst_recursive(root.left) == False:
        return False

    # 检查右子树是否为 BST
    if root.right and root.val >= root.right.val:
        return False
    if is_bst_recursive(root.right) == False:
        return False

    return True

解法 2:迭代

我们可以使用中序遍历来检查一棵二叉树是否为 BST。中序遍历将节点按从最小到最大的顺序访问。如果在中序遍历过程中,我们遇到一个节点的值小于前一个节点的值,则该二叉树不是 BST。

def is_bst_iterative(root):
    stack = []
    prev = None

    while stack or root:
        while root:
            stack.append(root)
            root = root.left

        root = stack.pop()

        # 检查当前节点是否大于前一个节点
        if prev and root.val <= prev.val:
            return False

        prev = root
        root = root.right

    return True

解法 3:基于范围

我们可以使用基于范围的解法来判断一棵二叉树是否为 BST。对于每个节点,我们定义一个范围,该范围包含该节点及其子树中所有节点的值。如果任一子树的范围与父节点的范围重叠,则该二叉树不是 BST。

def is_bst_range(root):
    def helper(node, lower, upper):
        if not node:
            return True

        # 检查节点是否在指定的范围内
        if node.val <= lower or node.val >= upper:
            return False

        # 递归检查左子树和右子树
        return helper(node.left, lower, node.val) and helper(node.right, node.val, upper)

    return helper(root, float('-inf'), float('inf'))

复杂度分析

三种解法的复杂度都是 O(n),其中 n 是二叉树中的节点数。

总结

判断一棵二叉树是否为 BST 是算法面试中一个常见的问题。有递归、迭代和基于范围三种解法。每种解法都有其优点和缺点。递归解法是最直接的,但对于非常大的二叉树可能存在栈溢出的风险。迭代解法不需要额外的空间,但可能更难理解。基于范围的解法可以快速检测出违反 BST 性质的节点,但需要维护每个节点的范围,这可能会增加额外的开销。