[转载] Catalan数及其应用

来源:互联网 发布:免费视频监控软件 编辑:程序博客网 时间:2024/05/27 08:13

什么是Catalan数

        说到Catalan数,就不得不提及Catalan序列,Catalan序列是一个整数序列,其通项公式是我们从中取出的C_n就 叫做第n个Catalan数,前几个Catalan数是:1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, …咋看之下没什么特别的,但是Catalan数却是许多计数问题的最终形式。

Catalan数的一些性质

        Catalan数的基本公式就是上个部分所列出的那样,但是却有一些变形和具体的性质:

1、C_n = {2nchoose n} - {2nchoose n+1} quad nge 0

这是根据原来的式子推导出来的,大概过程是这样的:C_n = frac{1}{n+1}{2nchoose n} = {2nchoose n} -  frac{n}{n+1}{2nchoose n} = {2nchoose n} -  {2nchoose n + 1}

2、C_0 = 1 quad , quad C_{n+1}=frac{2(2n+1)}{n+2}C_n

这个递推式很容易可以从原来的式子中获得

3、begin{displaymath}C_0 = 1 quad , quad C_{n+1}=sum_{i=0}^{n}C_i,C_{n-i}quad nge 0end{displaymath}

4、begin{displaymath}C_n= frac 1{n+1} sum_{i=0}^n {n choose i}^2end{displaymath}

5、begin{displaymath}C_n sim frac{4^n}{n^{frac{3}{2}}sqrt{pi}}end{displaymath}

这个是Catalan数的增长趋势。

Catalan数在组合计算中的应用

        在《组合数学》(机械工业出版社)一书中,介绍Catalan数是由其一个应用推导出的公式,其具体的描述如下:

        n个+1和n个-1构成2n项a_1,a_2,...,a_n,其部分和满足a_1 + a_2 + ... + a_k ge 0 quad , quad 0 le k le 2n的序列个数等于第n个Catalan数C_n

其证明也不难,我们假设不满足条件的序列个数为U_n,那么就有C_n + U_n = {2n choose n}。剩下的工作就是求U_n了,我们假设有一个最小的k令a_1 + a_2 + ... + a_k < 0。由于这里k是最小的,所以必有a_1 + a_2 + ... + a_{k - 1} = 0 quad , quad a_k = -1,并且k是一个奇数。此时我们将前k项中的+1变为-1,将-1变为+1,那么就得到一个有(n+1)个+1和(n-1)个-1的序列了,这样的序列个数就是我们要求的U_n,数值大小为U_n = {2nchoose n + 1}。那么我们就得到了C_n = {2nchoose n} - U_n = {2nchoose n} - {2nchoose n + 1}}},就是我们前面的公式。

        在具体的组合数问题中,很多都可以转换为Catalan数进行最后的计算,如下:

1、如上文所说,对于任意的k,前k个元素中-1的个数小等于+1的个数的序列计数,我们可以不停地变换形式,比如将-1看成右括号,+1看成左括号,就变成了合法括号表达式的个数。比如2个左括号和2个右括号组成的合法表达式有C_2 = 2种,是()()和(())。

2、既然如上一点都把括号加上去了,那么顺便就再次转换,n+1个数连乘,乘法顺序有C_n种,比如我们三个数连乘a*b*c,那么等于在式子上加括号,有2种乘法顺序,分别是(ab)c和a(bc)。貌似对应关系比较模糊,我们取n为3来看看,n为3的时候就是4个数相乘了,那么我们设为abcd,最初的标号定在a上,我们对于n为3得到合法的括号序列有5个,分别是:((())),()(()),()()(),(())()和(()()),那么我们将一个左括号看成是当前操作数指针往右移动一个位置,一个右括号看成是当前操作数和左边最近的一块操作数相乘起来,那么对应的五个表达式就是:a(b(cd)),(ab)(cd),((ab)c)d,(a(bc))d和a((bc)d),他们之间是一一对应关系。

3、n个节点的二叉树的所有可能形态数为C_n,这一点很容易证明,我们考虑随便取一个节点作为根,那么他左边和右边的儿子节点个数就确定了,假定根节点标号为x,那么左子树的标号就从1到x-1,共x-1个,右子树的标号就从x+1到n,共n-x个,那么我们的x从1取到n,就获得了所有的情况数begin{displaymath}C_n = sum_{i = 0}^{n - 1}C_i,C_{n - i - 1}end{displaymath}。这个式子就是我们性质3的式子。

4、n个非叶节点的满二叉树的形态数(对称后得到的二叉树除非自己本身对称,否则算是不同),这里取Wikipedia上的一张图片说明问题:

[转载] Catalan数及其应用 - coder007 - Coder007的博客

这里要求满二叉树,实际上就是在上一点的每个子节点的空儿子上都加上叶子,就形成了我们的图了,那么我们要求的结果就是Catalan数。

5、对于一个n*n的正方形网格,每次我们能向右或者向上移动一格,那么从左下角到右上角的所有在副对角线右下方的路径总数为C_n。同样引用Wikipedia上的一张图片来表示:

[转载] Catalan数及其应用 - coder007 - Coder007的博客

我们将一条水平边记为+1,垂直边记为-1,那么就组成了一个n个+1和n个-1的序列,我们所要保证的就是前k步中水平边的个数不小于垂直边的个数,换句话说前k个元素的和非负,就是我们关于Catalan数的定义。

6、凸n+2边形进行三角形分割(只连接顶点对形成n个三角形)数:

[转载] Catalan数及其应用 - coder007 - Coder007的博客

7、n个数入栈后的出栈的排列总数是C_n。例如1,2,3入栈的出栈排序有123,132,213,231和321五种

8、对于集合{1,2,...,2n}的不交叉划分的数目为C_n,这里解释一下不交叉划分,我们对于集合{a,b}和{c,d},假设他们组成了两个区间[a,b]和[c,d],我们假设两个区间不重合,那么以下四种情况当做是不交叉的:a<c<d<b,a<b<c<d,c<a<b<d与c<d<a<b,就是说两个区间可以包含或者相离,那么此时我们称集合{a,b}和{c,d}是不交叉的。对于集合{1,2,...,2n},将里面元素两两分为一子集,共n个,若任意两个子集都是不交叉的,那么我们称此时的这个划分为一个不交叉划分。此时不交叉的划分数就是我们的C_n了,证明也很容易,我们将每个子集中较小的数用左括号代替,较大的用右括号代替,那么带入原来的1至2n的序列中就形成了合法括号问题,就是我们第二点的结论。例如我们的集合{1,2,3,4,5,6}的不交叉划分有五个:{{1,2},{3,4},{5,6}},{{1,2},{3,6},{4,5}},{{1,4},{2,3},{5,6}},{{1,6},{2,3},{4,5}}和{{1,6},{2,5},{3,4}}。

9、n层的阶梯切割为n个矩形的切法数也是C_n。如下图所示:

[转载] Catalan数及其应用 - coder007 - Coder007的博客

这个证明是怎么进行的呢?我们先绘制如下的一张图片,即n为5的时候的阶梯:

[转载] Catalan数及其应用 - coder007 - Coder007的博客

我们注意到每个切割出来的矩形都必需包括一块标示为*的小正方形,那么我们此时枚举每个*与#标示的两角作为矩形,剩下的两个小阶梯就是我们的两个更小的子问题了,于是我们的C_5 = C_0 * C_4 + C_1 * C_3 + C_2 * C_2 + C_1 * C_3 + C_0 * C_4注意到这里的式子就是我们前面的性质3,因此这就是我们所求的结果了。

10、在一个2*n的格子中填入1到2n这些数值使得每个格子内的数值都比其右边和上边的所有数值都小的情况数也是C_n

11、平面上连接可以形成凸包的2n个点分成2个一组连成n条线段,两两线段之间不相交的情况总数是C_n,这里实际上和第7点本质上是一样的,这里就不解释了。

Catalan数问题的一个变形:

        n+m个人排队买票,并且满足n ge m,票价为50元,其中n个人各手持一张50元钞票,m个人各手持一张100元钞票,除此之外大家身上没有任何其他的钱币,并且初始时候售票窗口没有钱,问有多少种排队的情况数能够让大家都买到票。

        这个题目是Catalan数的变形,不考虑人与人的差异,如果m=n的话那么就是我们初始的Catalan数问题,也就是将手持50元的人看成是+1,手持100元的人看成是-1,任前k个数值的和都非负的序列数。

        这个题目区别就在于n>m的情况,此时我们仍然可以用原先的证明方法考虑,假设我们要的情况数是D_{n+m},无法让每个人都买到的情况数是U_{n + m},那么就有D_{n + m} + U_{n +m} = {n + m choose n},此时我们求U_{n + m},我们假设最早买不到票的人编号是k,他手持的是100元并且售票处没有钱,那么将前k个人的钱从50元变成100元,从100元变成50元,这时候就有n+1个人手持50元,m-1个手持100元的,所以就得到U_{n + m} = {n + m choose n + 1},于是我们的结果就因此得到了,表达式是D_{n + m} = {n + m choose n} - {n + m choose n + 1}

        关于Catalan数的变形还有很多,本身组合数学就是一门十分有趣的学科,通过不停地分析,求解我们能够不断增加自己思维的严谨性和全面性。Catalan数中涉及到了关于组合数的求解问题,这个问题实际上可以详细地展开,内容十分丰富,涉及面也很广,留在下一次继续说明。

其他问题:

1、n个元素的二叉查找树有多少种。
2、n*n棋盘从左下角走到右上角而不穿过主对角线的走法。
3、2n个人排队买票问题,票价50,n个人拿50元,n个人拿100元,售票处无零钱,能顺利卖票的所有排队方式。
4、n个元素全部入栈并且全部出栈的所有可能顺序。

        这些问题的答案都是卡特兰数F(n)。但是很明显可以看出后三个问题是同质的。都可以抽象成2n个操作组成的操作链,其中A操作和B操作各n个,且要求截断到操作链的任何位置都有:A操作(向右走一步、收到50元、元素入栈)的个数不少于B操作(向上走一步、收到100元找出50元、元素出栈)的个数。故问题2、3、4其实是同一个问题。

        下面先证明问题2、3、4和问题1同解,再证明问题2、3、4的解是F(n)=C(2n,n)/(n+1),从而证明问题1的解也是F(n)=C(2n,n)/(n+1)。

1、问题2、3、4和问题1同解
        问题1的解是F(n)=∑(k=0…n-1){F(k)*F(n-1-k)},因为一棵n个结点的二叉排序树的根可以是1到n的任意结点,设为k,则其左子树结点个数为k,左子树的种类一共有F(k-1)种,右子树结点个数为n-k,右子树的种类一共有F(n-k)。而究竟哪一点为根可以有1到n共n个选择,故k取遍1到n——F(n)=∑(k=1…n){F(k-1)*F(n-k)}=∑(k=0…n-1){F(k)*F(n-k-1)}。

        如果我们能证明问题2的解也可表示为F(n)=∑(k=0…n-1){F(k)*F(n-1-k)},就完成了证明。

        考虑n*n棋盘,记主对角线为L。从左下角走到右上角不穿过对角线L的所有路径,不算起点,一定有第一次接触到L的位置(可能是终点),设此位置为M,坐标为(x,x)——设第一个数为横轴坐标。该路径一定从下方的(x,x-1)而来,而起点处第一步也一定是走向(1,0),两者理由相同——否则就穿过了主对角线。考虑从(1,0)到(x,x-1)的(x-1)*(x-1)的小棋盘中,因为在此中路径一直没有接触过主对角线(M的选取),所以在此小棋盘中路径也一定没有穿过从(1,0)到(x,x-1)的小棋盘的对角线L1。这样在这个区域中的满足条件的路径数量就是一个同构的子问题,解应该是F(x-1),而从M到右上角终点的路径数量也是一个同构的子问题,解应该是F(n-x),而第一次接触到主对角线的点可以从(1,1)取到(n,n),这样就有F(n)=∑(k=1…n){F(k-1)*F(n-k)}=∑(k=0…n-1){F(k-1)*F(n-k)}。证毕。

2、问题2的解为F(n)=C(2n,n)/(n+1)
        思路是先求所有从(0,0)到(n,n)的路径数X,再求所有穿过主对角线L的从(0,0)到(n,n)的路径数Y,用前者减去后者得到所求。从(0,0)到(n,n)的路径数显然是C(2n,n),一共要走2n步到达右上角,其中向右和向上各n步,总走法是C(2n,n)。考虑一个新增的位置(n-1,n+1),它位于终点的左上角一个格处,设所有从(0,0)到(n-1,n+1)的路径数为Z,下面要证明Y和Z相等,从而通过求Z来求Y。考虑从(0,1)到(n-1,n)的对角线L2,对于所有穿过L而到达终点的路径,一定会接触到L2,找出某路径第一次接触到L2的位置M1,将从M1到终点的路径沿L2做对折一定会得到一条从M1到(n-1,n+1)的路径,故每条穿过L到达终点的路径都对应一条到达(n-1,n+1)的路径,即有Y<=Z。所有从起点到达(n-1,n+1)的路径都一定会穿过L2,找出某路径第一次穿过L2的位置M2,将M2到(n-1,n+1)的路径沿L2对折,就得到一条M2到(n,n)的路径,且该条路径一定穿过L,故每条到达(n-1,n+1)的路径都对应一条穿过L到达终点的路径,即有Z<=Y。

故Z==Y。
        接下来通过求Z来求Y。Z是显然的从(0,0)到(n-1,n+1)共需走2n步,其中向右n-1步、向上n+1步,故Z=C(2n,n-1)。由以上可知F(n)=X-Y=X-Z=C(2n,n)-C(2n,n-1)=C(2n,n)/(n+1)。证毕。

        由以上可知问题1的解也是F(n)=C(2n,n)/(n+1),故求和(k){F(k)*F(n-1-k)}=C(2n,n)/(n+1)。这个数称为卡特兰数,前几项为1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796。

        除了上面描述的四个问题外,它对应的问题还有:
矩阵链所有乘法顺序问题(同问题1)。
凸多边形剖分成三角形的方法数(同问题1)。