卡特兰数在数据结构中的运用

卡特兰数在数据结构中的运用

问题引入

问题背景

总共有2n次选择,每次可以选A或选B,选A和B的总次数均为n,要求每个前缀序列中A都不少于B,求这样的序列的个数。

卡特兰数

这里首先给出,上面问题的结果为卡特兰数。

具体的证明过程参见后文的“卡特兰数在数据结构中的应用-进出栈序列的可能性问题”部分。

另一种理解卡特兰数的方法

从递推公式中可以看出,只要问题符合以下的性质,就可以考虑使用卡特兰数进行表示。

  1. 总问题通过不同的划分方法分别分割成两个子问题,子问题也满足此性质
  2. 两个子问题求解结果之积就是在这种划分下的结果
  3. 最终结果就是不同划分下的结果之和

上面所说的“问题背景”就符合这种性质。

  1. 假设最后出栈的数是第 i ​ i​ i 个数,那么它入栈之前一定有 i − 1 ​ i-1​ i1​ 个数字完成了进栈出栈(子问题1),它入栈之后也一定有 n − i ​ n-i​ ni 个数字完成了进栈出栈(子问题2)
  2. 固定这个数最后出栈时,结果为子问题1和子问题2结果的乘积
  3. 每个数都可能作为最后一个数出栈,因此最终结果就是不同划分下的结果之和

卡特兰数的递归定义

f ( n ) = ∑ k = 0 n − 1 f ( k ) f ( n − 1 − k ) = 4 n − 2 n + 1 f ( n − 1 ) , n ≥ 1 f ( 0 ) = 1 f(n) = \sum\limits_{k=0}^{n-1} f(k) f(n-1-k) = \frac{4n-2}{n+1}f(n-1),n\ge 1 \\ f(0) = 1 f(n)=k=0n1f(k)f(n1k)=n+14n2f(n1),n1f(0)=1


f ( n + 1 ) = ∑ i = 0 n f ( i ) f ( n − i ) f ( 0 ) = 1 f(n+1) = \sum\limits_{i=0}^{n} f(i) f(n-i) \\ f(0) = 1 f(n+1)=i=0nf(i)f(ni)f(0)=1

卡特兰数的通项公式

C a t a l a n ( n ) = 1 n + 1 C 2 n n = C 2 n n − C 2 n n − 1 {\rm Catalan} (n) = \frac{1}{n+1} C_{2n}^{n} = C_{2n}^n - C_{2n}^{n-1} Catalan(n)=n+11C2nn=C2nnC2nn1

至于如何相互推导,可以用生成函数法,但是这样写下去就没完了(手动狗头)

这里放一个链接:神奇的卡塔兰(Catalan)数 - 知乎 (zhihu.com)

卡特兰数在数据结构中的应用

进出栈序列的可能性问题

进栈记为+1,出栈记为-1

合法序列满足总和为0,且每个前缀的和大于等于0

正好是卡特兰数“使用背景”中提到的条件

因此n个元素合法的进出栈序列有 1 n + 1 C 2 n n \frac{1}{n+1} C_{2n}^{n} n+11C2nn

结论推导

通过补集思想进行计算

最终推导得出 C 2 n n − C 2 n n − 1 C_{2n}^n - C_{2n}^{n-1} C2nnC2nn1 的结果

  1. 将进出栈表示为+1、-1:如果有n个元素进行进出栈操作,则必须操作2n次,且其中必须含有n次进栈和n次出栈,所以如果通过-1、+1来表示进栈和出栈的操作,那么所有操作的和必然为0;
  2. 非法序列:通过组合数 C 2 n n C_{2n}^n C2nn 可以计算出所有操作的为0的进出栈序列,但是其中混有一些非法的序列,比如说在n=3时,序列:-1,+1,-1,+1,+1,-1,这个序列的第三项是在空栈的时候进行出栈操作,显然是错误的,所以需要排除这类的序列。
  3. 前缀和:在排除非法序列之前,先引进了一种前缀和的概念,前缀和就是一个长度k序列,前1项、前2项…前k项的和。分析一下,对于上一条中满足所有操作和为0序列,根据栈的性质,一个序列前缀和只要出现小于0的数,则可以判定这个序列是非法序列,所以只需要把这种具有前缀和小于0的序列剔除掉,那么剩下的序列就是合法的进出栈方式。
  4. 第一个值为-1的前缀和:一个进出栈序列如果出现值小于0的前缀和,就肯定能找到找到第一个值为-1的前缀和,如序列:-1,+1,-1,+1,+1,-1,其中-1、+1、-1这个前缀和就是第一个值为-1的前缀和,通过这个前缀和就可以把序列分为两部分,其中第一部分-1,+1,-1,第二部分+1,+1,-1,第一部分的-1数量比+1多1,第二部分的+1数量比-1多1,此时将第一部分全部取反,得到序列+1,-1,+1,+1,+1,-1,此时在整个序列中+1的个数比-1的个数多了2个。所有的非法序列都符合这个规律,故将其推广。设A是包含长度为2n的非法序列的集合,对A中的所有元素第一个值为-1的前缀和取反。可以得到集合B,B中元素的序列中+1的数量比-1的数量多两个,+1的数量是n+1,-1的数量是n-1,且总能找到一个值为+1的前缀和。
  5. 对于B中元素的数量是容易计算的,B中的元素要满足两个条件,一是有n+1个+1,n-1个-1,二是总能找到一个值为+1的前缀和,分析一下,实际上只要满足第一个条件就必定满足第二个条件,因为+1的数量总比-1多1(最极端的情况是所有-1都排前面,但这个时候也满足第一个条件),所以只要计算满足第一个条件序列的就可以计算出B中的元素数量,通过组合数 C 2 n n + 1 C_{2n}^{n+1} C2nn+1 就可以算出。
  6. 现在只要证明A中元素的数量和B中元素的数量相等就可以了,实际上在A中任意元素的第一个值为-1的前缀和取反,都可以在B中找到唯一的一个元素与之对应,同理,在B中对任意的元素的第一个值为+1的前缀和取反,都可以在A中找到唯一的元素与之对应,故A与B中的元素是一一对应的关系,所以A中元素的数量就是 C 2 n n + 1 C_{2n}^{n+1} C2nn+1
  7. 所以最后就是用总的元素数 C 2 n n C_{2n}^n C2nn 减去非法序列数 C 2 n n + 1 C_{2n}^{n+1} C2nn+1 ,最后就可以得到所有的可能进出栈序列数 1 n + 1 C 2 n n \frac{1}{n+1} C_{2n}^{n} n+11C2nn

注:这一段内容参考了BV1wr4y1q7qw的Peter9997的评论,如有侵权可联系删除

与栈有关的拓展应用:括号匹配

把左括号看成+1,把右括号看成-1即可

给定结点数求二叉树的形态数

n n n 个结点的二叉树有几种形态

f ( 0 ) = 1 f ( 1 ) = 1 f ( 2 ) = 2 f ( 3 ) = 4 . . . f ( n ) = f ( 0 ) f ( n − 1 ) + f ( 1 ) f ( n − 2 ) + . . . + f ( n − 1 ) f ( 0 ) f ( n ) = ∑ i = 0 n − 1 f ( i ) f ( n − 1 − i ) f(0) = 1\\ f(1) = 1\\ f(2) = 2\\ f(3) = 4\\ ...\\ f(n) = f(0)f(n-1) + f(1)f(n-2) + ...+ f(n-1)f(0) \\f(n)= \sum\limits_{i=0}^{n-1}f(i)f(n-1-i) f(0)=1f(1)=1f(2)=2f(3)=4...f(n)=f(0)f(n1)+f(1)f(n2)+...+f(n1)f(0)f(n)=i=0n1f(i)f(n1i)
选择一个节点作为根节点,其左子树可以有0, 1, …, n-1个结点,其余结点在右子树上

根节点固定,形态数 = 左子树的形态数 * 右子树的形态数

把n种不同根节点的情形加起来即可

给定结点数求满二叉树的形态数

预备知识:

满二叉树的定义本质就是说没有度为1的结点

度为0的结点个数记为 n 0 n_0 n0,度为1的结点个数记为 n 1 n_1 n1,度为2的结点个数记为 n 2 n_2 n2

只要是二叉树,就有 n 0 = n 2 + 1 n_0 = n_2 + 1 n0=n2+1

对满二叉树进行深度优先遍历,向左为+1,向右为-1

因此如果有n个度为2的非叶结点,就需要向左向右各进行一次访问子树操作

而且对于同一个根节点,向左操作一定在向右操作之前

这就符合了卡特兰数的“应用背景”

因此形态数为 C a t a l a n ( n 2 ) {\rm Catalan} (n_2) Catalan(n2)

卡特兰数在实际问题中的应用

  1. 有2n个人排成一行进入剧场。入场费5元。

    其中只有n个人有一张5元钞票,另外n人只有10元钞票,剧院无其它钞票。

    问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票找零?

    (将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)

  2. 求将一个凸多边形区域分成三角形区域的方法数

    (固定一条边,然后找不同的顶点与这条边构成三角形,这个三角形将把这个n边形划分为i+1边形和n-i边形,记 h n h_n hn为n+1边形的划分方法,则有
    h n = ∑ k = 1 n − 1 h k h n − k h 1 = 1 h_n = \sum\limits_{k=1}^{n-1} h_k h_{n-k}\\ h_1 = 1 hn=k=1n1hkhnkh1=1
    这个式子的结果也是卡特兰数,但首项可能有点不一样,可以记住五边形有5种划分)

  3. 在n×n的网格上,每次只能向右或向上走一格,在不穿越网格主对角线的情况下,从左下角(0,0)走到右上角(n,n)的不同路径计数。

    (每一步都可以选择时向右走或者向上走,向右和向上的步数相同,且规定前缀序列中向右步数不小于向上步数)

  4. 在圆上选择2n个点,将这些点成对连接起来,使得所得到的n条线段不相交的方法数。

    (沿着圆周看,弦的起始点记为+1,终点记为-1,且要求前缀和不小于0——卡特兰数)

    在思考这个问题时,注意不要想偏,我们是要求方法数的,只要抽象出的情况和实际问题的情况数一一对应即可。当你想“为什么前缀和不小于0可以确保弦不相交”这个问题时,请赶紧停下来,否则就可能像我一样让一下午的时间悄悄溜走。

    事实是,这样的逻辑抽象并不能确保弦不相交,但如果我们规定弦是不相交的,就能使得这种+1和-1所组成的一个序列刚好对应一种确定的生成弦的方法,因此两个问题的情况是一一对应的,情况数是相等的。

    如果弦可以相交的话,那么一个+1-1的序列就可以连出好多种弦来,这时候就没什么意义了。也就是说,正是因为规定了弦不能相交,我们才可以把这两种情形对应起来。

参考资料

n个节点的二叉树有多少种形态(Catalan数)_n个结点的二叉树有几种形态-CSDN博客

「算法入门笔记」卡特兰数 - 知乎 (zhihu.com)

卡特兰数 - 知乎 (zhihu.com)

【浅析】栈的卡特兰数_哔哩哔哩_bilibili

卡特兰数 — 计数的映射方法的伟大胜利 | Math173 (lanqi.org)

神奇的卡塔兰(Catalan)数 - 知乎 (zhihu.com)

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值