📅  最后修改于: 2023-12-03 15:36:03.305000             🧑  作者: Mango
二叉树中最大的BST是指二叉树中最大的二叉搜索子树。
本套装2中包含以下内容:
给定一棵二叉树的根节点root,求其中最大的二叉搜索子树的大小。
二叉搜索树的定义:对于任意一个节点,它的左子树中所有节点的值都小于该节点的值,右子树中所有节点的值都大于该节点的值。
例如,如下图所示的二叉树,其中3、4、5、6是它的最大BST子树。
对于每个节点,判断以该节点为根的子树是否为二叉搜索树。
如果是,计算该子树的大小并更新最大值。
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$为二叉树的节点个数。