📅  最后修改于: 2023-12-03 15:12:01.214000             🧑  作者: Mango
给定一棵二叉树,求其中存在多少个二叉搜索树。
在二叉搜索树中,左子树节点的值均小于当前节点的值,右子树节点的值均大于当前节点的值。因此,如果某个节点的左子树和右子树都是二叉搜索树,那么从该节点到根节点的路径上的所有节点都是二叉搜索树。
因此,我们可以从叶节点开始逐步向上计算,在计算某个节点时,如果它的左子树和右子树都是二叉搜索树,则可以将它自己作为根节点构建一棵二叉搜索树,这样就可以得到一棵新的二叉搜索树。而它的父节点只需要计算在以该节点为根节点的子树中存在多少个二叉搜索树即可。
因此,我们可以定义一个函数 count_bst(root)
,用来计算以 root
为根节点的子树中存在多少个二叉搜索树。在该函数中,如果 root
为 None
,则直接返回 0,否则,我们可以分别计算它的左子树、右子树和它本身构成的二叉搜索树的个数。
根据乘法原理,左子树中存在 x
个二叉搜索树,右子树中存在 y
个二叉搜索树,且左子树的最大值小于 root
的值,右子树的最小值大于 root
的值。则构成新的二叉搜索树的方式有 C(x+y, x)
种。
因此,我们可以使用递归的方式计算二叉树中存在的二叉搜索树的数量。最终返回以根节点为根节点的子树中存在的二叉搜索树的数量。
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def count_bst(root: TreeNode) -> int:
if not root:
return 0
# 计算左子树中存在的二叉搜索树的数量
left_bst_count = count_bst(root.left)
# 计算右子树中存在的二叉搜索树的数量
right_bst_count = count_bst(root.right)
# 判断左子树和右子树的最大、最小值
left_max = root.left.val if root.left else float('-inf')
right_min = root.right.val if root.right else float('inf')
# 计算以root为根节点的子树中存在的二叉搜索树的数量
bst_count = 1
for i in range(left_bst_count + 1):
for j in range(right_bst_count + 1):
if left_max < root.val < right_min:
bst_count += math.comb(left_bst_count + right_bst_count, left_bst_count)
return bst_count
对于一棵 n 个节点的二叉树,计算中每个节点最多被计算 1 次,因此总时间复杂度为 O(n^2),其中计算组合数的时间复杂度为 O(n)。
算法使用了递归,递归深度最大为二叉树的高度,因此空间复杂度为 O(log n)。