一、引入
首先思考这样一个问题:给定n个不同的正整数1~n,依次进行出栈入栈操作,出栈的顺序有多少种?
对于每个正整数都会入栈一次、出栈一次,我们将入栈记为+1,出栈记为-1,会得到如下的序列:
+1,-1,+1,+1,....,+1,-1,记总和为total,因为每个元素只会分别入栈出栈各一次,所以total=0
又因为栈中的元素个数不可能为负数,由此可以得到这个序列的所有前缀和均大于等于0
我们记其中一个前缀串中,+1的个数为x,-1的个数为y,会得到x-y>=0(即任意一个前缀和大于等于0),即y<=x,其中1<=x<=n,1<=y<=n
从图中看就是选出一条路径从(0,0)到达(n,n),只能向右或向上走,并且不能越过y=x这条直线的路径即为合法的出栈序列,那么出栈序列数即为这样的路径数记为
那么如何求呢?
合法路径数=总路径数-非法路径数
先求总路径数,在次移动中选
次向右移动,即
。
再求非法路径数,即越过对角线的路径
把这条线画出来,碰到即说明是一条非法路径。
所有的非法路径与这条线有至少一个交点,把第一个交点设为(a,a+1),把(a,a+1)之后的路径全部按照 这条线对称过去,这样,最后的终点就会变成(n-1,n+1)。
所有非法路径对称后都唯一对应着一条到(n-1,n+1)的路径,所以非法路径数就是,合法路径数就是
,即
继续推导:
继续推导不难得出如下的通项公式:
即为卡特兰数
二、算法例题:
Python代码如下:
n = int(input())
f = [0]*20
f[0] = 1
for i in range(1,n+1):
f[i] = f[i-1]*(4*i-2)//(i+1)
print(f[n])
三、卡特兰数的应用
1、一个有n个0和n个1组成的字串,且所有的前缀字串皆满足1的个数不超过0的个数。这样的字串个数有多少?
将0记为+1,1记为-1。
2、包含n组括号的合法运算式的个数有多少?
对于左括号入栈记为+1,出栈记为-1
3、n个节点可构造多少个不同的二叉树?
我们采用数组存储二叉树的节点:即可得到1、0交错的数组,由二叉树的性质可以得知:前缀串中0的个数不超过1的个数。到此我们又将这个问题转化成了问题1,将1记为+1,0记为-1
4、在圆上选择2n个点,将这些点成对连接起来使得所得到的n条弦不相等的方法数?
从左上第一个点开始按照顺时针进行连接,出点记为+1,入点记为-1,对于一个合法连接可以看到前缀和总是大于等于0,下面举一个反例
由于圆形的对称性,我们从第一个出点开始,即一个+1开始,图中的绿点开始到第三个点前缀和为-1,不合法
由此我们又将此问题转化为了问题1
5、通过连结顶点而将n+2边的凸多边形分成n个三角形的方法数?
通项公式推导过程: