固定 root 节点,剩下的 n-1 个节点将分别放在左子树和右子树。计算以每个数为根节点的二叉搜索树数量,最后相加求和
class Solution(object):
global memo
memo = collections.defaultdict(int)
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
if n ==0 or n==1:
return 1
count = 0
if memo.has_key(n):
return memo.get(n)
for i in range(n): #n个节点的可以组成的不同的二叉树的数量
left = self.numTrees(i)
right = self.numTrees(n-i-1)
count += left*right
memo[n] = count
return count
动态规划,n个节点的树的数量等于以i(1到n)为根节点二叉树的数量之和,
假设 n 个节点存在二叉排序树的个数是 G (n),令 f(i) 为以 i 为根的二叉搜索树的个数,则
G(n)=f(1)+f(2)+f(3)+f(4)+…+f(n)
当 i 为根节点时,其左子树节点个数为 i-1 个,右子树节点为 n-i,则
f(i)=G(i−1)∗G(n−i) 左子树的数量乘以右子树的数量就是以i为根节点的二叉搜索树的数量
综合两个公式可以得到 卡特兰数 公式
G(n)=G(0)∗G(n−1)+G(1)∗(n−2)+…+G(n−1)∗G(0)
def numTrees(self, n):
"""
:type n: int
:rtype: int
"""
memo = [0]*(n+1)
memo[0],memo[1] = 1,1
for i in range(2,n+1):
for j in range(1,i+1):
memo[i] += memo[i-j] * memo[j-1]
return memo[n]