卡特兰数 卡塔兰数 概念 代码实现 模型分析全集

特别鸣谢

参考1

参考2

参考3

概念

情境导入

一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?

可以形象化地转化为括号问题,更好理解,进栈是(,出栈是),下面为n=3的全部序列

  1. 首先,我们设 f(n)=序列个数为n的出栈序列种数。
  2. 同时假定,从开始到栈第一次出到空为止,这段过程中第一个出栈的序数是k。特别地,如果栈直到整个过程结束时才空,则k=n。
  3. 首次出空之前第一个出栈的序数k将1 ~ n的序列分成两个序列:其中一个是1 ~ k-1,序列个数为k-1;另外一个是k+1 ~ n,序列个数是n-k。
  4. 此时,我们若把k视为确定一个序数,那么根据乘法原理,f(n)的问题就等价于——序列个数为k-1的出栈序列种数乘以序列个数为n - k的出栈序列种数(一种递归的思想),即选择k这个序数的f(n)=f(k-1)×f(n-k)。
  5. 而k可以选1到n,所以再根据加法原理,将k取不同值的序列种数相加,得到的总序列种数为:f ( n ) = f (0)\cdot f(n-1) + f(1)\cdot f(n-2)+......+f(n-1)\cdot f(0)

抽象分析

经过上面的分析我们抽象出了一类函数:f ( n ) = f (0)\cdot f(n-1) + f(1)\cdot f(n-2)+......+f(n-1)\cdot f(0)

这就是卡特兰数的递推式

我们把f换成C表示,有如下公式

递推公式2是我们要用代码实现的部分,方便多次询问查询

如果仅仅查询一次,可以离线计算组合数使用通项公式1或者性质

性质推导见模型分析1

C0 = 1,         
C1 = 1,         C2 = 2,          C3 = 5,          C4 = 14,          C5 = 42,
C6 = 132,       C7 = 429,        C8 = 1430,       C9 = 4862,        C10 = 16796,
C11 = 58786,    C12 = 208012,    C13 = 742900,    C14 = 2674440,    C15 = 9694845,
C16 = 35357670, C17 = 129644790, C18 = 477638700, C19 = 1767263190, C20 = 6564120420, ...

代码实现

//函数功能: 计算Catalan的第n项
//函数参数: n为项数
//返回值:  第n个Catalan数
int N=20;
int h[N];
int Catalan(int n)
{
	if(n<=1) return 1;
	h[0] = h[1] = 1;        //h(0)和h(1)
	for(int i=2;i<=n;++i)    //依次计算h(2),h(3)...h(n)
	{
		h[i] = 0;
		for(int j = 0; j < i; j++) //根据递归式计算 h(i)= h(0)*h(i-1)+h(1)*h(i-2) + ... + h(i-1)h(0)
			h[i] += (h[j] * h[i-1-j]);
	}
	int result = h[n]; //保存结果
	return result;
}

模型分析

我们要想办法把相关问题转化为括号问题(出栈问题)

1. 01序列

给出一个n,要求一个长度为2n的01序列,使得序列的任意前缀中1的个数不少于0的个数, 有多少个不同的01序列?
以下为长度为6的序列:
111000 101100 101010 110010 110100

其本质就是括号问题/入栈问题:
1. 因为对于每一个数来说,必须进栈一次、出栈一次。我们把进栈设为状态‘1’,出栈设为状态‘0’。n个数的所有状态对应n个1和n个0组成的2n位二进制数。
2. 由于等待入栈的操作数按照1‥n的顺序排列、入栈的操作数b大于等于出栈的操作数a(a≤b),因此输出序列的总数目=由左而右扫描由n个1和n个0组成的2n位二进制数,1的累计数不小于0的累计数的方案种数。
 

操作及性质推导如下

其解等于第n个Catalan数。

2. 标准Young表

将 1~2n 填入一个 2n 的方格表中,使得每一行自左而右、每一列自上而下都是严格增的。

当 n=3 时,有5种不同的标准Young表:

如果第一行表示“(”的位置、第二行表示“)”的位置,那么每个“标准Young表”都对应一个“匹配的括号串”。

其解等于第n个Catalan数。

3. 找零问题

2n个人要买票价为五元的电影票,每人只买一张,但是售票员没有钱找零。其中,n个人持有五元,另外n个人持有十元,问在不发生找零困难的情况下,有多少种排队方法?

其本质是“01序列”的变式:
我们把持有五元的人设为状态‘1’,持有十元的人设为状态‘0’。2n个人的所有状态对应n个 ‘1’ 和n个 ‘0’ 组成的2n位二进制数。
由于必须先有1个持有五元的人排在1个持有十元的人的前面,才能不发生找零困难,因此不发生找零困难排队方法的总数目=由左而右扫描由n个 ‘1’ 和n个 ‘0’ 组成的2n位二进制数,1的累计数不小于0的累计数的方案种数。
 

其解等于第n个Catalan数。

4. 二叉树计数

有n个节点构成的二叉树(非叶子节点都有2个儿子),共有多少种情形?
有n+1个叶子的二叉树的个数?

举例:n=3的情况:
在这里插入图片描述

 

其解等于第n个Catalan数。

5.  凸多边形划分

在一个n边形中,通过不相交于n边形内部的对角线,把n边形拆分为若干个三角形,问有多少种拆分方案?

如五边形有如下5种拆分方案:
在这里插入图片描述
如六边形有如下14种拆分方案:
在这里插入图片描述

其中f(2)相当于矩形被分成两部分,我们仍然看成三部分,其中一部分是一条线,无法组成三角形,为便于计算设f(2)=1

其解等于第n-2个Catalan数。

6. 圆上n条线段

在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数?

 其解等于第n个Catalan数。

7. 不相交的弦

在一个圆周上分布着 2n个点,两两配对,并在这两个点之间连一条弦,要求所得的 n 条弦彼此不相交。

当 n=3时,有如下5种不同的连弦方式:

从某一个特定的点开始,逆时针“前进”,如果“遇到”了“新的”弦,则写下一个“(”,如果“遇到”了“旧的”弦,则写下一个“)”。不相交的弦就转化为匹配的括号串。

转化为括号问题,其解等于第n个Catalan数。

8. 笔画“群峰”

使用 n个斜向上的线段和 n个相同长度的斜向下的线段,画出群峰。

当 n=3时,可以画出以下5种不同的群峰:

当 n=4时,可以画出以下14种不同的群峰:

 

如果用“(”取代斜向上的线段,用“)”取代斜向下的线段,则转化为“括号匹配”问题。

考虑第一次“回到水平面”的位置,可以如下分为和自身相同但是规模变小的两个子问题:

9. 格路问题

原点格路问题

从 (0,0) 点出发,每步只能沿 x 轴或 y 轴的正方向每步走一个单位,最终走到 (m,n) 点,有多少条路径?

格路问题的一般化

不能“接触”对角线的格路问题 

 当m=n+1时,利用组合数性质转化为卡特兰数

在这里插入图片描述 

 

在这里插入图片描述 

 

不能过对角线的格路问题

当m=n时,转化为卡特兰数 

 在这里插入图片描述

在这里插入图片描述 

 在这里插入图片描述

10. 填充阶梯图形

用n个长方形填充一个高度为n的阶梯状图形的方法个数?

举例:n=4的情况
在这里插入图片描述

 其解等于第n个Catalan数。

一些简单的变式不再列举,当你能列出性质式C(2n,n)-C(n2,n-1)或者递推式的时候,就是卡塔兰数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值