栈和卡特兰数(Catalan number)

栈和卡特兰数(Catalan number)

1.饭后,姐姐洗碗,妹妹把姐姐洗过的碗一个一个地放进碗橱摞成一摞。一共有n个不同的碗,洗前也是摞成一摞的,也许因为小妹贪玩而使碗拿进碗橱不及时,姐姐则把洗过的碗摞在旁边,问:小妹摞起的碗有多少种可能的方式?

2.给定n个数,有多少种出栈序列?

3.一个有n个1和n个-1组成的字串,且前k个数的和均不小于0,那这种字串的总数为多少?

这三个问题具有相同的结构,三个问题是可以互相转化。将姐姐放碗看做入栈操作,将妹妹放碗看做出栈操作。则问题一变为问题二。将入栈操作记为1,出栈记为-1,问题2变为问题3。

问题的答案是一个著名的数列,卡特兰数。该问题的代数解法比较抽象,而运用到几何上,用图片来描述,却有让人恍然大悟的感觉。

  • 只有穿过虚线的部分才会映射新路线 找到新路线条数即可找到穿过的条数

事实上,可以认为问题是,任意两种操作,要求每种操作的总次数一样,且进行第k次操作2前必须先进行至少k次操作1。我们假设一个人在原点,操作1是此人沿右上角45°走一个单位(一个单位设为根号2,这样他第一次进行操作1就刚好走到(1,1)点),操作2是此人沿右下角45°走一个单位。第k次操作2前必须先进行至少k次操作1,就是说明所走出来的折线不能跨越x轴走到y=-1这条线上!在进行n次操作1和n此操作2后,此人必将到到达(2n,0)!若无跨越x轴的限制,折线的种数将为C(2n,n),即在2n次操作中选出n次作为操作1的方法数。

请添加图片描述

现在只要减去跨越了x轴的情况数。对于任意跨越x轴的情况,必有将与y=-1相交。找出第一个与y=-1相交的点k,将k点以右的折线根据y=-1对称(即操作1与操作2互换了)。可以发现终点最终都会从(2n,0)对称到(2n,-2)。由于对称总是能进行的,且是可逆的。我们可以得出所有跨越了x轴的折线总数是与从(0,0)到(2n,-2)的折线总数。而后者的操作2比操作1要多0-(-2)=2次。即操作1为n-1,操作2为n+1。总数为C(2n,n-1)。
请添加图片描述

代码实现

//函数功能: 计算Catalan的第n项
//函数参数: n为项数(小于100)
//返回值:  第n个Catalan数
int Catalan(int n)
{
	if(n<=1) return 1;
	int *h = new int [n+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]; //保存结果
	delete [] h;       //注意释放空间
	return result;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

追寻远方的人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值