卡特兰数相关整理

卡特兰数

计算公式

卡特兰数的递推公式是:
C(0)= 1 C(1)=1

C(n) = C(0) C(n-1) + C(1) C(n-2) + …… + C(n-1) C(0) (注意里面的加起来是n-1,因为算是n个里面选定了一个,剩下的个数就是n-1)


在这里插入图片描述

计算结果:

在这里插入图片描述

但是就是要分清楚题目给的n到底是什么含义,到底是n还是2n,真正算下去列出来的式子是怎么样的。

常见问题:(1)(2)(3)(7)(9)(10)(11)(12)是一类,都是01序列类,可以直接分析列式的。(4)(5)(6)(8)是一类,需要列出递归式来求的。当然,在本质上,以上所有问题均能抽象为一种问题:一种通解符合卡特兰数列的问题。

  1. n对括号 有多少种组合
  2. 矩阵链乘,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,有几种括号化的方案
  3. n个元素入栈 有多少种出栈顺序
  4. 凸多边形通过互不相交的对角线划分,求划分方案数
  5. 在圆上选择2n个点,将这些点连接起来,使得所得到的n条线段不相交的方法数
  6. 2n边的凸多边形,连接对角线 可以分出三角形的个数
  7. n × n格点中不越过对角线的单调路径的个数(上班路线选择问题)
  8. 给定n个节点组成二叉搜索树个数(或组成的二叉树形态数)
  9. 2n个高矮不同的人 站成两排 保证后排对应的人比前排高 每排从左到 右越来越高 有多少种排列方式
  10. 《编程之美》4.3中的买票找零问题:2n个人排队买票,其中n个人持50元,n个人持100元。每张票50元,且一人只买一张票。初始时售票处没有零钱找零。请问这2n个人一共有多少种排队顺序,不至于使售票处找不开钱
  11. (腾讯笔试)在图书馆一共6个人在排队,3个还《面试宝典》一书,3个在借《面试宝典》一书,图书馆此时没有了面试宝典了,求他们排队的总数?
  12. (阿里笔试)说16个人按顺序去买烧饼,其中8个人每人身上只有一张5块钱,另外8个人每人身上只有一张10块钱。 烧饼5块一个,开始时烧饼店老板身上没有钱。 16个顾客互相不通气,每人只买一个。 问这16个人共有多少种排列方法能避免找不开钱的情况出现。

序列类问题

可以抽象为寻找符合若干条件的0-1序列的数量 (这个条件就是要根据题目要求来分析,比如什么一定要在什么前面)

这类问题的解法很巧妙,没有构造递推,直接得出通项公式

路径数目

问题:求在N*N个格点中不越过对角线的单调路径的个数

这个路径需要满足的条件:(用数学、公式什么的来描述清楚问题)

  1. String[i]=[X|Y]
  2. String.length=2n
  3. X与Y数量相等,均为n。
  4. 所有的前缀字串(首项为String[0]的子串)皆满足X的个数大于等于Y的个数 (才能不越过对角线)

​ 满足(1)(2)(3)项的String的数量我们已经计算出为C(2n)(n)个,现考虑计算该集合下不满足(4)的情形的数量,然后减去该种情况,得到最终结果。

​ 现从头遍历一个不满足(4)的String,记为BadStr,当遍历到第2m+1位上时有m+1个Y和m个X(容易证明一定存在这样的情况),则后面剩下的部分中必有n-m个X和n-m-1个Y将第2m+2位及其以后的部分做以下变换:X变成Y、Y变成X,则该部分的X现在有n-m-1个,Y有n-m个,变换后字符串记为cBadStr中共有n+1个Y和n-1个X的二进制数。注意到,对于每个BadStr,均一一对应与一个这样的cBadStr,因此NumOf(BadStrs) = NumOf(cBadStrs)=C(2n)(n−1)。因此满足(1)~(4)的String数量为C(2n)(n)−C(2n)(n−1)

出入栈问题

问题:对于一个无限大的栈,一共n个元素,请问有几种合法的入栈出栈形式。

​ 就可以转化为01序列的问题,用1表示进栈,用0表示出栈。整个序列里的0和1的个数相等,且整个序列里任何位置,从开始到这个位置的1的个数一定得大于等于0的个数。跟上一题是一样的。

矩阵链乘(组括号)问题

问题:P=A1×A2×A3×……×An,依据乘法结合律,不改变其顺序,只用括号表示成对的乘积,试问有几种括号化的方案?

​ 同样转化为01序列的问题,用1表示左括号,0表示右括号。就是从左到右扫描,无论扫描到任何位置,左括号数一定要大于或者等于右括号数。

​ n个矩阵需要连乘(n-1)次,因此需要(n-1)对括号。且这里的括号只是为了使矩阵两两结合,而不是单纯为加括号而加括号,像( (a1) * (a2)),这里将两个矩阵分别括起来是不符合要求的。因此这里如果确定了括号的顺序,那么矩阵的结合顺序也会确定,如(()())对应了(( a1* a2) * (a3 * a4))。注意到是(n-1)对括号,即(n-1)个左括号和(n-1)个右括号,那么应该使用f[2(n-1)]来计算。

买票找零(或借书)问题

问题:16个人按顺序去买票,票价为50元,其中8个人每人身上只有一张50块钱,另外8个人每人身上只有一张100块钱。求要在售票员没有初始金钱的情况下顺利购票的排队方案

​ 带50块钱的排前面的个数总是要大于带100块钱的人的个数。

照相排队问题(阿里、腾讯笔试题)

问题:12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?

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

​ 这个问题的Catalan数列“隐藏”的稍微深一些,需要我们做一些分析。
​ 我们先把这12个人从低到高排列,维护一个12位的01序列,从左到右分别对应这12个由低到高排好序的人,用0表示对应的人在第一排,用1表示对应的人在第二排,其中0出现的个数和1出现的个数相等。通过这种方式得到的两排人,每排都是从矮到高排列的。也就是按排好的这12个人的序列,不管是被分到第一排还是第二排,都是按这个顺序来的。那么接下来的问题就是保证第二排比第一排对应的人高。然后就又转化为01序列里,经过的0的个数要大于等于经过的1的个数。

就是得先转化一下问题,先做一些处理,而不是一开始就弄成序列来分析,有些条件要求是可以先处理掉的。

扩展:如果要打印所有排队方案呢?

​ 回溯法能够很好的解决这类问题。

​ 就是先递归往下取0或1,同时记录01的数目,不符合的就不取,取到最后可以了就得到一个01序列,然后根据这个序列来排列。

总结

​ 这种序列类的题都直接列**C(2n)(n)−C(2n)(n−1)**来做。

一般场景

​ 由递推公式求解卡特兰数。

二叉树数目问题

求N个节点构成的不同构的二叉树的个数/求N个大小不同的节点组成的二叉搜索树的不同形态数。

​ 就是要分析一下这个问题是由什么组成的,可以划分成什么子问题。一般树的问题都是选定了根结点,然后再去看子树。

  1. 先考虑只有一个节点的情形,设此时的形态由f(1)中,显然,f(1)=1;

  2. 如果有两个节点呢?现固定一个节点,那么另个节点会有左右子树两种分布情况,故有f(2)=f(1)+f(1);

  3. 再讨论三个节点的情形,仍然固定一个节点,即根节点,然后此时还剩两个节点,那么左右子树的总节点分布情况为(2,0),(1,1)和(0,2),f(3)=f(2)f(0)+f(1)f(1)+f(0)f(2)。f(0)表示什么也没有,不会增加额外的情况,故取值为1;

  4. 那么对于n个节点呢?同样,固定一个节点,那么左右子树的分布情况为(n-1,0),(n-2,1),(n-3,2)……(1,n-2),(0,n-1),故f(n)=f(n-1)f(0)+f(n-2)f(1)+……+f(1)f(n-2)+f(0)f(n-1)

    然后就可以由这个公式用程序去递归。n比较大的话递归会超时,就可以用带备忘录的递归或者动态规划。然后因为是直接用递归公式得到的,也没有要求n一定要是偶数,直接按着这个公式列就好。

    其实也就是选定一个,然后剩下的拆分成子问题。

    所以就是要注意n到底取值是什么,给的是n还是2n。

    干脆就直接列出式子,然后按Cn来做了。就是按

在这里插入图片描述

在这里插入图片描述

圆上点对互连问题

​ 在圆上选择2n个点,将这些点成对连接起来,且所得n条线段不相交,求可行的方法数。

​ 乍一看不能直接套公式。那么,先进行一下分析,将圆上的点依次标为P0,P1,…P2n-1。为了避免混淆,使用F(2n)表示2n个点可连成的线段数。选择Pk与P0相连(0<k<n),同样地可以看出,k必为奇数,否则1至k-1之间有奇数个点,不可能成对连成直线。同样地把k设为2i+1,那么线段P0Pk把剩余的点分为了1…2i和2i+2…2n-1,且新的连线不能与0k相交,它们只能属于0k划分出的这两个区域之一。即F(2n) = ∑F(2i)F(2n-1-(2i+2)+1) = ∑F(2i)F(2n-2i-2),其中i = 0 … n-1。这时,又转化成熟悉的形式了。

一开始看着没有想法,要用符号和公式表示出来,然后试一下选择的情况。不一定就是序列的问题,但是问题的形式是可以搞成用同样的式子来解。

​ 这道题还是和上面几道有些区别。前几道题你总是能区分哪些元素/操作是一类,其余的是另一类;而这个问题你如何区分这些看上去是一模一样的2n个点呢?怕是只有从分析入手、发现了其递推公式与卡特兰数的联系,从而才敢使用的吧。

一定要分析清楚特点和联系,把整个过程分析清楚。

多边形划分问题

将多边形划分为三角形问题。求一个凸多边形区域划分成三角形区域的方法数。

​ 多边形问题其实写出来就是,每次先选定一个点,然后开始有各种不同的划分,每种划分就可以划分出两个子区域,子区域内就是子问题,就又可以继续往下做。这样其实也还是有问题,就不能保证最后都是三角形,所以其实是选定一条边,然后再选定一个点作为顶点,这样每次划分就确定会有个三角形,还有两边的区域。选定任意一条边作为第一个三角形的边,如P1Pn,此时再为它选择一个顶点k,2<=k<=n-1,此时,n边型被分为了一个k边型(顶点编号由1到k)、一个三角形(顶点编号为1、k、n)、一个n-k+1边型(顶点编号由k到n)。然后就可以构造出一个式子递归来算。

​ 与前几个问题不同,这种划分方式总是合理的序列,也就是说,这样是在已知总是合法的情况下进行,而不像前几个问题,先判断怎样划分合法,再来划分。

总结

​ 相当于先选定一个,然后剩下的就可以划分成两个分别去做。初始状态一定是确定的,也就说,序列第一项是固定的,那么剩下的n-1项就可以用分治的思路分割成两个子序列去解决就可以了。抽象点概括下,就是对于问题A,规模为n,要解决这个问题,可以用分治的思想,首先固定其中某一个元素,将剩下的n-1个元素拆分成两个小问题,这两个小问题的规模分别是(0,n-1) (1,n-2) (2,n-3) … (n-1,0)
卡特兰数表现了一种符合乘法原理事件的本性,某种程度上,反映了我们思考问题的方式,故而能够在许多场合得到应用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值