Catalan数
卡特兰数用于解决一些特定的排列问题,一般是求解有多少种排列。
Catalan数的定义:
(1)当n=1时,C(1)=1。
(2)当n>1时,C(n) = C(1)*C(n-1) + C(2)*C(n-2) + ... + C(n-1)*C(1)
(3)当然,还能这样算:
(4)更厉害的,是可以这样算,但可能不精确: (ps:这些都是经过证明的公式)
注:所有的奇卡塔兰数(即n为奇数)Cn都满足。
一般来说,求卡特兰数有个基本问题,而其他问题一般可以转成这个问题。这个基本问题是这样的:一个n个bit的二进制数,如果其任意前缀都是1的个数>=0的个数,求这样的二进制有多少个?可以根据catellan数的性质直接求Cn即可。
经典题(1):有n对括号,请问n对括号能组成多少个合法序列?比如"(())"就是合法。
思路:考虑前i个pre[i],可以这样认为,其中的左括号为1,右括号为0,那么就成功转成了卡特兰数的一般问题了。这里有个问题,编程之美中提到,f(2*n)=[1/(n+1)]*C(2*n,m),其实右式完全等于求Cn,也可以直接按Cn来求。但是为什么书里这么写呢?因为书中考虑的是枚举k为每个可能与首个左括号匹配的右括号的位置,假如规定括号序列的下标是从0开始的,由于k必须是奇数位置才合法,所以列出来的公式为 f(2n)=f(0)*f(2n-2)+f(2)*f(2n-4)+...f(2n-4)*f(2)+f(2n-2)*f(0),观察到式子中没有出现求奇数的f,因此直接将0~2n-1中的偶数映射过来就是1~n啦。
经典题(2):12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应列的第一排的人高,问排列方式有多少种?
思路:先将12个人升序排序,下标分别为1~n。同样,用0代表首行,用1代表第二行。那么每个后缀back[i]中1的个数就必须大于等于0的个数了,否则肯定存在一个j>=i,首行[j]>次行[j],即第一行有个人比第二行高了,不合法。答案也是求Cn。
经典题(3):将一个具有n个顶点的凸多边形切成多个三角形的方法有多少种?注意只能某一顶点切往另一顶点。
思路:凸多边形的每条边必须对应一个三角形,那么现在的问题只是求这条边对应的另一个顶点在哪里。同样,这个顶点的位置也是枚举,那么就将问题分成了两个小问题,其实就是区间DP题。答案依然是Cn。
经典题(4):有3个人要借书,3个人要还书。要使得3个人都能借到书,那么这6人进馆的序列有多少种?
思路:将还书的人看成0,借书的人看成1。只能在有人还了之后才能有人借得到。那么每个前缀pre[i]中1的个数必须>=0的个数,又转成了一般问题。
同样的问题还有:”合法的入栈出栈序列有多少种?“和”合法的找钱给钱序列有多少种“等等。
经典题(5):将一个具有n个顶点的凸多边形切成多个三角形的方法有多少种?注意只能某一顶点切往另一顶点。
思路:凸多边形的每条边必须对应一个三角形,那么现在的问题只是求这条边对应的另一个顶点在哪里。同样,这个顶点的位置也是枚举,那么就将问题分成了两个小问题,其实就是区间DP题。答案依然是Cn。
经典题(6):一个n*n的网格,要从左下角的格子走到右上角的格子,在不踏入对角线的情况下,且第一步必须往右走,有多少种方案到达终点?
思路: 要不碰到对角线,那么往右走的次数要时刻多于等于往上走的次数。又是可以转成一般问题。
经典题(7):一个由n个节点组成的二叉树,不同构的有多少棵?
思路: 考虑第n个点为根,那么左边可能有0~n-1个点,右边就是剩下的点,枚举左边有多少个点即可。求Cn。
经典题(8):矩阵连乘问题,n个矩阵相乘,要求为他们加括号改变乘法的顺序,有多少种方法?
思路: 仍然是”合法的括号序列“的那道题。
总结:通过上面的题观察到,一共有两种类型,一种是”括号匹配“类型,一种是”基本问题“。如果需要匹配的,一般就是第一种类型,否则就是第二种。它们对应的模型都差不多。