LintCode解题记录-Catalan Number

来源:互联网 发布:文明5 贸易网络 编辑:程序博客网 时间:2024/05/18 01:40

Catalan Number 卡特兰数

1.基本定义

组合数学中的知识,定义:令h(0) = h(1) =1, 则若h(n) = h(0)*h(n-1)+h(1)*h(n-2)+…+h(n-1)*h(0) (n >= 2),则称h(n)为卡特兰数。
例如:
h(2) = h(0)*h(1) + h(1)*h(0) = 1*1 + 1*1 = 2,
h(3) = h(0)h(2) + h(1) h(1) + h(2) * h(0) = 1*2 + 1*1 + 2*1 = 5,
h(4) = 14, h(5) = 42,…
另类递推式: h(n) = h(n-1)*(4*n-2)/(n+1)
递推关系的解为: h(n) = C(2n, n)/(n+1), n=0,1,2…
递推关系的另类解为: h(n) = C(2n, n) - C(2n, n-1), n=0,1,2…
其中C(n, m)是从n中随机取m个的所有可能的取法(不考虑排列顺序)。

2.应用(重点)

1.矩阵链乘 括号化问题
令P = a1 x a2 x a3 x…x an,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方式?(h(n)种,暂时没懂)

2.出栈次序
一个栈(无穷大)的入栈序列为1,2,3,…,n,请问一共有多少种出栈方式?
Step1: 设f(n)=序列个数为n时出栈序列种数。假设最后出栈的元素为k,显然k的取值是[1, n],且k取不同值时情况是相互独立的,因此可用加法原则将所有的k得到的出栈方式相加即是f(n)。
Step2: 由于k是最后出栈,那么在k入栈之前,比k小的元素均出栈(栈的先入后出原则),即1~k-1个元素出栈,有f(k-1)种方式。
Step3: 而之后比k大的数入栈,且都在k之前入栈,即k+1~n元素出栈,有f(n-k)种方式。为什么是f(n-k)呢,因为其实数的大小并不重要,重要的是数的个数,比如1,2,3,4,5和6,7,8,9,10得到的出栈方式显然是一样的。而k+1~n之间共有n-k个数,所以他们的出栈方式就有f(n-k)种了。
Step4: 根据乘法法则,得到f(k-1)*f(n-k)种,那么f(n) = Σf(k-1)*f(n-k) (k=1,…,n)
观察可得,这个递推式就是Catalan数的递推公式。

类似问题:买票找零
有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?
答: 将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈,那么上述问题就变成了n个数入栈然后有多少种出栈方式,答案就是Catalan Number.

3.凸多边形三角划分
在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。给定凸多边形的边数n,求不同划分的方案数f(n)。
思路就是以某一条边为基准,以这条边的两个顶点为起点P1和终点Pn,将该凸多边形的顶点依次标记为P1,P2,…,Pn,再在该凸边形中找任意一个不属于这两个顶点的Pk(2 <= k <= n-1)来构成一个三角形,用这个三角形把该凸边形划分成了两个凸边形,其中一个凸边形是由P1,P2..,Pk组成的凸k边形,另一个则是由Pk,Pk+1,..,Pn组成的凸n-k+1边形。
那么根据乘法原理,此时的划分总是就是f(k)*f(n-k+1),再根据不同k的加法原理,得到f(n) = Σf(k)*f(n-k+1),k的取值为[2, n-1]。结合Catalan数的递推公式,可以发现f(n) = h(n-2)。

4.LintCode Unique BST
给定n个节点,问能组成多少种不同的二叉搜索树。
考虑顶点为k时的情况,那么其左子树就是1~k-1所能组成的二叉搜索树,右子树就是k+1~n所能组成的二叉搜索树。根据乘法原理,顶点为k时所能得到的结果就是f(k-1)*f(n-k),再依据加法原理,得到f(n) = Σf(k-1)*f(n-k),k=1,2..,n
代码

    int numTrees(int n) {        // write your code here        vector<int> dp(n+1, 0);        dp[0] = dp[1] = 1;        for (int i = 2; i <= n; i++) {            for (int j = 0; j < i; j++) {                dp[i] += dp[j] * dp[i-j-1];            }        }        return dp[n];    }

5.n对括号的正确匹配数
给定n对括号,求括号正确配对的字符串的个数。
考虑n对括号时任意一种配对方案,对于最后一个右括号,有与之唯一配对的左括号,于是该字符串可以理解为A(B),其中A和B也是正确配对的括号字符串。那么假设这个与之匹配的左括号是第k个左括号,显然第1~k-1个括号都在这个左括号之前得到了匹配,即上面所说的A,同理,k+1~n个左括号都在B中得到了匹配。依据乘法原理和加法原理,就可以得到f(n)=Σf(k-1)*f(n-k),k=1,2,..n,即Catlan Number。