一、卡特兰数


卡特兰数又称卡塔兰数,英文名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) 


也就是刚好是卡特兰数。



四、类似问题


类似于这样的问题还有矩阵链乘问题、凸多边三角形的划分、给定节点组成的二叉树。其本质都是递推的应用。