Catalan数(卡特兰数)

原文:http://buptdtt.blog.51cto.com/2369962/832586

  • Catalan数(卡特兰数)

规定h(0)=1,而h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,h(6)=132,h(7)=429,h(8)=1430,h(9)=4862,h(10)=16796,h(11)=58786,h(12)=208012,h(13)=742900,h(14)=2674440,h(15)=9694845·····················

通项公式为:

 

        递推公式为:

 h(n)=((4*n-2)/(n+1))*h(n-1)

h(n)= h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)h(0) (其中n>=2)

  • 应用

  1. n对括号有多少种匹配方式?

         思路n对括号相当于有2n个符号,n个左括号、n个右括号,可以设问题的解为f(2n)。第0个符号肯定为左括号,与之匹配的右括号必须为第2i+1字符。因为如果是第2i个字符,那么第0个字符与第2i个字符间包含奇数个字符,而奇数个字符是无法构成匹配的。

       通过简单分析,f(2n)可以转化如下的递推式 f(2n) = f(0)*f(2n-2) + f(2)*f(2n - 4) + ... + f(2n - 4)*f(2) + f(2n-2)*f(0)。简单解释一下,f(0) * f(2n-2)表示第0个字符与第1个字符匹配,同时剩余字符分成两个部分,一部分为0个字符,另一部分为2n-2个字符,然后对这两部分求解。 f(2)*f(2n-4)表示第0个字符与第3个字符匹配,同时剩余字符分成两个部分,一部分为2个字符,另一部分为2n-4个字符。依次类推。

       假设f(0) = 1,计算一下开始几项,f(2) = 1, f(4) = 2, f(6) = 5。结合递归式,不难发现f(2n) 等于h(n)

     2. n个节点构成的二叉树,共有多少种情形?

       思路:可以这样考虑,根肯定会占用一个结点,那么剩余的n-1个结点可以有如下的分配方式,T(0, n-1),T(1, n-2),...T(n-1, 0),设T(i, j)表示根的左子树含i个结点,右子树含j个结点。

       设问题的解为f(n),那么f(n) = f(0)*f(n-1) + f(1)*f(n-2) + .......+ f(n-2)*f(1) + f(n-1)*f(0)。假设f(0) = 1,那么f(1) = 1, f(2) = 2, f(3) = 5。结合递推式,不难发现f(n)等于h(n)

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

      思路:这个与加括号的很相似,进栈操作相当于是左括号,而出栈操作相当于右括号。n个数的进栈次序和出栈次序构成了一个含2n个数字的序列。第0个数字肯定是进栈的数,这个数相应的出栈的数一定是第2i+1个数。因为如果是2i,那么中间包含了奇数个数,这奇数个肯定无法构成进栈出栈序列。

       设问题的解为f(2n), 那么f(2n) = f(0)*f(2n-2) + f(2)*f(2n-4) + f(2n-2)*f(0)。f(0) * f(2n-2)表示第0个数字进栈后立即出栈,此时这个数字的进栈与出栈间包含的数字个数为0,剩余为2n-2个数。f(2)*f(2n-4)表示第0个数字进栈与出栈间包含了2个数字,相当于1 2 2 1,剩余为2n-4个数字。依次类推。

       假设f(0) = 1,计算一下开始几项,f(2) = 1, f(4) = 2, f(6) = 5。结合递归式,不难发现f(2n) 等于h(n)

     4. 描述:有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?

     思路:可以将持5元买票视为进栈,那么持10元买票视为5元的出栈。这个问题就转化成了栈的出栈次序数。由应用三的分析直接得到结果,f(2n) 等于h(n)*n!*n!

 

package com.daqing.cat;

import java.util.Stack;



/**

 *猫和老鼠做游戏,其中猫赢了M次,老鼠赢了N次(N>M)

 *且中间过程中没有一次猫赢的次数超过老鼠

 *

 *可以把问题看成是N次入栈操作,M次出栈操作,总共有多少种方式,递归调用

 */

public class CatAndMouse {
    static final int M = 2;
    static final int N = 2;
    static int count = 0;//记录总数

    public static void main(String[] args) {
        nextStep(0,0,true,0);
        System.out.println("最多可能比赛得分过程:"+count);
    }
    
    /*递归调用函数,下一步的操作,判断下一次可能的操作,判断是否执行到完毕
    * next ? true 入栈,false 出栈  
    * stackSize 表示栈的大小 
    */

    public static void nextStep(int countN,int countM,boolean next,int stackSize){

        if(next){   
            stackSize++;//入栈
            countN++;
        }

        else{
            stackSize--;//出栈
            countM++;
        }

        if(countN<N){//接着入栈
            nextStep(countN,countM,true,stackSize);
        }
        if(countM<M && stackSize>0){//接着出栈
            nextStep(countN,countM,false,stackSize);
        }

        if(countN==N && countM==M){//找到一种可能
            count++;
        }

    }

}

 

posted @ 2014-05-06 17:34  EchoLee  阅读(244)  评论(0编辑  收藏  举报