📜  二叉树中最大的BST |套装2(1)

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

二叉树中最大的BST |套装2

二叉树中最大的BST是指二叉树中最大的二叉搜索子树。

本套装2中包含以下内容:

  1. 求二叉树中最大的BST的问题描述
  2. 暴力解法的思路和代码实现
  3. 优化解法的思路和代码实现
  4. 解法优化的时间复杂度分析
问题描述

给定一棵二叉树的根节点root,求其中最大的二叉搜索子树的大小。

二叉搜索树的定义:对于任意一个节点,它的左子树中所有节点的值都小于该节点的值,右子树中所有节点的值都大于该节点的值。

例如,如下图所示的二叉树,其中3、4、5、6是它的最大BST子树。

example

暴力解法
思路

对于每个节点,判断以该节点为根的子树是否为二叉搜索树。

如果是,计算该子树的大小并更新最大值。

代码实现
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


def largest_bst(root: TreeNode) -> int:
    def is_bst(root: TreeNode, min_val=float('-inf'), max_val=float('inf')):
        if not root:
            return True
        if not min_val < root.val < max_val:
            return False
        return is_bst(root.left, min_val, root.val) and is_bst(root.right, root.val, max_val)

    def helper(root: TreeNode):
        if not root:
            return 0
        if is_bst(root):
            return count_node(root)
        return max(helper(root.left), helper(root.right))

    def count_node(root: TreeNode) -> int:
        if not root:
            return 0
        return 1 + count_node(root.left) + count_node(root.right)

    return helper(root)
时间复杂度

对于每一个节点,需要递归判断其子树是否为二叉搜索树,因此时间复杂度为$O(N^2)$,其中$N$为二叉树的节点个数。

优化解法
思路

在暴力解法中,对于相同的子树,我们的判断是重复的,因此可以考虑优化。

我们可以在遍历的过程中记录每个节点的上下界,然后直接判断是否符合要求。

此外,我们还可以利用二叉搜索树的性质,对所有的节点分别记录其子树中的最小值和最大值,通过比较最小值和最大值来判断该子树是否符合要求。这样可以减少判断的次数。

代码实现
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


def largest_bst(root: TreeNode) -> int:
    def helper(root: TreeNode, lb, ub):
        if not root:
            return 0
        if lb <= root.val <= ub and helper(root.left, lb, root.val) and helper(root.right, root.val, ub):
            return count_node(root)
        return max(helper(root.left, lb, ub), helper(root.right, lb, ub))

    def count_node(root: TreeNode) -> int:
        if not root:
            return 0
        return 1 + count_node(root.left) + count_node(root.right)

    return helper(root, float('-inf'), float('inf'))
时间复杂度

在最坏情况下,每个节点都会被遍历一遍,因此时间复杂度为$O(N)$,其中$N$为二叉树的节点个数。