神奇的卡特兰数

首先看一道笔试题:

神奇的卡特兰数_第1张图片
笔试题

这个题的答案是,根据卡特兰数公式,所有的输出总数为5次,减掉3(标识符不能数字开头)开头的2个,所以最终答案是3个。
那么什么是卡特兰数呢?
卡特兰数:规定C0=1,而C1=1,C2=2,C3=5,C4=14,C5=42,C6=132,C7=429,C8=1430,C9=4862,C10=16796,C11=58786,C12=208012,C13=742900,C14=2674440,C15=9694845····································
原理如下:
令h(0)=1,h(1)=1,catalan数满足递推式[1]:h(n)= h(0) h(n-1)+h(1)h(n-2) + ... + h(n-1)h(0) (n>=2)   
例如:h(2)=h(0) h(1)+h(1)h(0)=1 1+11=2   h(3)=h(0) h(2)+h(1)h(1)+h(2) h(0)=12+1 1+21=5   
另类递推式:    h(n)=h(n-1) (4n-2)/(n+1);   
递推关系的解为: h(n)=C(2n,n)/(n+1) (n=0,1,2,3,...)   
递推关系的另类解为: h(n)=C(2n,n)-C(2n,n+1)(n=0,1,2,3,...)

C语言应用:

void catalan() //求卡特兰数
{
    int i, j, len, carry, temp;
    a[1][0] = b[1] = 1;
    len = 1;
    for(i = 2; i <= 100; i++)
    {
        for(j = 0; j < len; j++) //乘法
        a[i][j] = a[i-1][j]*(4*(i-1)+2);
        carry = 0;
        for(j = 0; j < len; j++) //处理相乘结果
        {
            temp = a[i][j] + carry;
            a[i][j] = temp % 10;
            carry = temp / 10;
        }
        while(carry) //进位处理
        {
            a[i][len++] = carry % 10;
            carry /= 10;
        }
        carry = 0;
        for(j = len-1; j >= 0; j--) //除法
        {
            temp = carry*10 + a[i][j];
            a[i][j] = temp/(i+1);
            carry = temp%(i+1);
        }
        while(!a[i][len-1]) //高位零处理
        len --;
        b[i] = len;
    }
}

下面是一些大公司的笔试题
先来一道阿里巴巴的笔试题目:
16个人按顺序去买烧饼,其中8个人每人身上只有一张5块钱,另外8个人每人身上只有一张10块钱。烧饼5块一个,开始时烧饼店老板身上没有钱。16个顾客互相不通气,每人只买一个。问这16个人共有多少种排列方法能避免找不开钱的情况出现。
答案:C8=1430,所以总数=14308!8!
腾讯实习招聘笔试题
在图书馆一共6个人在排队,3个还《面试宝典》一书,3个在借《面试宝典》一书,图书馆此时没有了面试宝典了,求他们排队的总数?
答案:C3=5;所以总数为53!3!=180.
12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
这个笔试题,很坑爹,因为把某个递归关系隐藏得很深。
首先来问题分析:
我们先把这12个人从低到高排列,然后,选择6个人排在第一排,那么剩下的6个肯定是在第二排。
用0表示对应的人在第一排,用1表示对应的人在第二排,那么含有6个0,6个1的序列,就对应一种方案。
比如000000111111就对应着
第一排:0 1 2 3 4 5
第二排:6 7 8 9 10 11
010101010101就对应着
第一排:0 2 4 6 8 10
第二排:1 3 5 7 9 11
问题转换为,这样的满足条件的01序列有多少个。
观察1的出现,我们考虑这一个出现能不能放在第二排,显然,在这个1之前出现的那些0,1对应的人
要么是在这个1左边,要么是在这个1前面。而肯定要有一个0的,在这个1前面,统计在这个1之前的0和1的个数。
也就是要求,0的个数大于1的个数。
OK,问题已经解决。
如果把0看成入栈操作,1看成出栈操作,就是说给定6个元素,合法的入栈出栈序列有多少个。
这就是神奇的卡特兰数!!!

你可能感兴趣的:(神奇的卡特兰数)