一、卡特兰数
卡特兰数又称卡塔兰数,英文名Catalan number,是 组合数学 中一个常出现在各种计数问题中出现的 数列 。由以 比利时 的数学家欧仁·查理·卡塔兰 (1814–1894)命名。在这里表示对数学家的尊敬,同时。。。也因为他发明了这些难懂的东西,脑袋都被这些数学家弄炸了。
首先是卡特兰数的定义:令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)。
可以根据上面的递推公式,写出递归的计算方案。
#include <stdio.h>
#include <assert.h>
int catalan(int n)
{
assert(n>=0);
if(0==n || 1==n)return 1;
int num=0;
for(int i=0;i<n;i++)
{
//在这里递归
num+=catalan(i)*catalan(n-i-1);
}
return num;
}
int main()
{
//输出正确结果
printf("%d\n",catalan(8));
return 0;
}
这里我们可以采用循环的形式来优化。这里我就不再细提,接着往下看。
二、卡特兰数的另一个递归解
h(n)=c(2n,n)-c(2n,n+1)(n=1,2,3,...)
其中c为组合数。
三、栈出栈顺序
题目:一个含有N个不同元素的待入栈序列,问存在多少种不同的出栈顺序。
解:这道题采用穷举显然不合适,可能会出现的方案有很多。我们在这里注意一下采用卡特兰数的思想。
我们将所有的出栈顺序按照出栈首个元素来分类:
a1(剩余序列),a2(剩余序列)......ai(剩余序列).......an(剩余序列)。
这样我们就可以采用递归的方法了。
我们就其中任意一种情况来分析,ai(剩余序列),如果ai是第一个出栈的,那么可以将整个序列分成两部分,一部分是a1~ai-1,一部分是ai+1~an。
前面一部分的出栈种类是C(i-1)。后面一部分序列是C(n-i),那么总共的序列是C(i-1)*C(n-i)。
那么考虑所有的n中情况。我们可以知道:
C(n)=C(0)*C(n-1)+C(1)*C(n-2) + ... + C(n-1)C(0)
也就是刚好是卡特兰数。
四、类似问题
类似于这样的问题还有矩阵链乘问题、凸多边三角形的划分、给定节点组成的二叉树。其本质都是递推的应用。