这是Leetcode第96题,给定一个 \(n\),求共有多少种不同的 \(BST\)(二叉搜索树)。
这道题实际上是 卡塔兰数 (Catalan Numbe) 的一个例子,也是很经典的一个问题了。下面,了解一下什么是卡特兰数以及它的性质。
卡特兰数是一种经典的组合数,经常出现在各种计算中,其前几项为 : 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, ...
卡特兰数满足以下性质:
令\(h(0)=1,h(1)=1\),catalan数满足递推式:
\[ h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2) \]
由此可以得出卡塔兰数列的递推式为:
\[ h(n)=C(2n,n)/(n+1) \]
或者
\[ h(n)=C(2n,n)-C(2n,n-1);(n=0,1,2...) \]
卡特兰数经常出现在OI以及ACM中,在生活中也有广泛的应用。下面举几个例子。
1、进出栈问题
栈是一种先进后出(FILO,First In Last Out)的数据结构.如1,1,2,3,4顺序进栈,那么一种可能的进出栈顺序是:1In→2In→2Out→3In→4In→4Out→3Out→1Out, 于是出栈序列为1,3,4,2。那么一个足够大的栈的进栈序列为1,2,3,⋯,n时有多少个不同的出栈序列?2、二叉树构成问题。
有n个结点,问总共能构成几种不同的二叉树。3、凸多边形的三角形划分。
一个凸的n边形,用直线连接他的两个顶点使之分成多个三角形,每条直线不能相交,问一共有多少种划分方案。4、在n*n的格子中,只在下三角行走,每次横或竖走一格,有多少中走法?
其实向右走相当于进栈,向左走相当于出栈,本质就是n个数出栈次序的问题,所以答案就是卡特兰数。
class Solution:
def numTrees(self, n: int) -> int:
res = [0 for i in range(n+1)]
res[0] = 1
res[1] = 1
for i in range(2,n+1):
for j in range(i):
res[i] += res[j] * res[i-j-1]
return res[n]