📜  门| GATE-CS-2009 |问题 5(1)

📅  最后修改于: 2023-12-03 15:42:16.979000             🧑  作者: Mango

题目描述

给定一棵二叉树,编写一个函数来检查它是否为二叉搜索树(BST)。 在二叉搜索树中,左子树的所有节点都小于根节点,右子树的所有节点都大于根节点,并且左右子树本身也必须是二叉搜索树。

函数签名
def is_valid_bst(root: TreeNode) -> bool:
    pass
输入
  • 根节点 root 是二叉树的根节点,类型为 TreeNode 对象。
输出
  • 返回一个布尔值,表示给定的二叉树是否为二叉搜索树。
示例
示例 1

输入:

    2
   / \
  1   3

输出: True

示例 2

输入:

    5
   / \
  1   4
     / \
    3   6

输出: False

解释: 根节点的值为 5,其左子树中的值为 1,右子树中的值为 4,且右子树的左子树中包含了小于根节点的值,因此该二叉树不是二叉搜索树。

解题思路
递归法

二叉搜索树的性质要求,左子树中的所有节点都应该小于根节点,右子树中的所有节点都应该大于根节点。因此,在每个节点中加入一个最大值和最小值的限制以确保其满足要求。

先考虑递归终止条件:

  • 如果当前节点为空节点,说明已经遍历完了该子树,返回 True
  • 若当前节点的值小于等于 min_val 或者大于等于 max_val,说明不满足二叉搜索树的条件,返回 False

递归调用:

  • 对于左子树,最大值应该是当前节点的值,最小值不变
  • 对于右子树,最小值应该是当前节点的值,最大值不变

将左右子树的结果进行与操作,即可得到最终结果。

中序遍历法

二叉搜索树的中序遍历的结果应当是递增的,因此可以进行中序遍历,判断遍历结果是否为递增的。

对于每个节点的值,需要保证它大于等于前一个节点(若前一个存在),则需要额外维护一个变量 prev_node,记录前一个节点的值。

时间复杂度
  • 递归法:$O(N)$,其中 $N$ 为节点数量,每个节点只遍历了一次
  • 中序遍历法:$O(N)$,需要进行一次中序遍历
代码实现
递归法
def is_valid_bst(root: TreeNode) -> bool:
    def dfs(node, min_val, max_val):
        if node is None:
            return True
        if min_val is not None and node.val <= min_val:
            return False
        if max_val is not None and node.val >= max_val:
            return False
        return dfs(node.left, min_val, node.val) and dfs(node.right, node.val, max_val)

    return dfs(root, None, None)
中序遍历法
def is_valid_bst(root: TreeNode) -> bool:
    if root is None:
        return True

    def inorder(node):
        nonlocal prev_node
        if node is None:
            return
        inorder(node.left)
        if prev_node is not None and node.val <= prev_node.val:
            nonlocal is_valid
            is_valid = False
            return
        prev_node = node
        inorder(node.right)

    prev_node = None
    is_valid = True
    inorder(root)
    return is_valid