Catalan数,括号序列和栈

全是入门的一些东西.基本全是从别处抄的.

: 支持单端插入删除的线性容器. 也就是说,仅允许在其一端加入一个新元素或删除一个元素. 允许操作的一端也叫栈顶,不允许操作的一端也叫栈底.

数个箱子相叠就可以认为是一个栈,只能在最顶端加入一个新箱子或拿走一个箱子.

栈中的元素遵循后进先出(last in first out,LILO)的规律.即:更早出栈的元素,应为更早入栈者.

这是一个演示:

奇数行为栈中元素(右端可以进行插入删除),元素以逗号隔开, EMPTY表示栈为空

偶数行为进行的操作

EMPTY
插入10
10
插入20
10,20
插入51
10,20,51
插入10
10,20,51,10
删除一个元素
10,20,51
删除一个元素
10,20
插入30
10,20,30
删除一个元素
10,20
删除一个元素
10
删除一个元素
EMPTY

栈混洗问题

给出三个栈S1,S2,S3,一开始S1中含有1到n的n个数字且从栈顶到栈底数字依次为1,2,3,....n-1,n.

只有两种允许的操作:

A S1非空时从S1取出一个元素放入S2,

B S2非空时可以从S2取出一个元素放入S3.

最后S3中自底向上形成的序列称作一个栈混洗.

例如,如果S1中一开始有1,2,3,4四个元素,那么先进行4次A操作再进行4次B操作,将得到序列4,3,2,1.如果A操作和B操作交替进行,将得到序列1,2,3,4.

显然,栈混洗的结果并不唯一.

一个长为n的序列的栈混洗可以表示成n次A操作和n次B操作组成的一个操作序列. 而n次A操作和n次B操作组成的一个操作序列也可以表示唯一的一个栈混洗序列.

不同的操作序列必然得到不同的栈混洗,不同的栈混洗也必然对应不同的操作序列.

并不是所有含有n个A,n个B的序列都是合理的操作序列.例如BBBBAAAA,将导致我们尝试拿出空栈S2中的元素.

一个序列合理的条件是:对于任意m(1<=m<=2n),该序列的前m个操作中,B操作的数目不超过A操作的数目.只要满足这个条件就能保证任意时刻不会拿出空栈中的元素.

如何判断一个栈混洗序列是否是可能出现的栈混洗序列

例如,对于序列1,2,3,通过栈混洗可以得到[1,2,3],[3,2,1],[1,3,2],[2,1,3],[2,3,1],但是无法得到[3,1,2].如果使3最先出栈,那么就必须先令1,2入栈,从而2会在1之前出栈,只能得到[3,2,1]

任意给出一个n和一个排列,如何判断这个排列能否通过栈混洗得到?例如,n=5,序列为5,4,1,3,2,是否可能?

直接的思路是,直接根据我们要得到的序列,尝试进行A操作和B操作.例如,n=5时,要使序列的第一个元素为5,就必须一直进行A操作直到5出现在S2的栈顶.之后需要4,4恰好在S2的栈顶,于是弹出4.接下来需要的1不在栈顶,因此这个序列无法通过栈混洗得到.时间复杂度显然为O(n).其正确性也是显然的.

栈混洗与括号序列

首先只考虑由一种括号组成的括号序列.

()()()(),(()())(),((()))都是能够匹配的括号序列.)(,))(,())(都是不能够匹配的括号序列.

只要将A操作与左括号"("对应,B操作与右括号")"对应,栈混洗的合法操作序列就可以和能够匹配的括号序列一一对应.

例如,AABB对应(()),ABAB对应()()

按照我们之前的理解,如果保证序列中左右括号数目相同,那么我们只需要扫描一遍序列并维护一个计数器,初始为0,遇到左括号+1,遇到右括号-1,只要这个计数器的数值始终非负,就说明任意一个前缀中左括号的数目多于右括号的数目,等价于这个序列是能够匹配的括号序列.

另一种判断括号序列是否合法的方法:初始化一个空栈S,从左向右扫描序列,遇到一个左括号将其入栈,遇到一个右括号时判断栈中是否有一个左括号,如果有,那么这个左括号与当前遇到的右括号相匹配.如果栈为空,那么这个括号序列并不合法.通过这种方式,我们除了得知括号序列是否合法,还可以得知每个右括号具体是和哪个左括号匹配,还可以处理序列中出现了多种括号且只有对应种类的括号能匹配的情况.可以自行尝试,"维护一个计数器"的方式并不能方便地扩展到多种括号的情况.

拓展:允许循环移位的合法括号序列

允许将括号序列的最左侧元素拿到最右边,问能否通过若干次这样的操作使得括号序列合法.

首先这样的序列仍然需要满足左括号和右括号数目相同. 但是除此之外还需要满足什么条件呢?

令人惊讶的是,除此之外并不需要满足什么条件.只要左括号和右括号数目相同,就可以保证能够通过若干次循环移位使得括号序列合法.

给出一个构造方式:将左括号视为1,右括号视为-1,求取该序列的前缀和.如果前缀和中的最小值为0那么序列本身就是合法的.否则我们找到前缀和的最小值的出现位置(多个数值相同时取最左侧的),将这个位置之前的一段序列移位到右端,得到的即为合法的括号序列.构造方式的正确性不难证明.

括号序列计数

有多少个不同的含有n对括号的合法括号序列?这个问题等价于通过栈混洗可以得到多少个不同序列.也等价于,有多少个含有n个0,n个1的长为2n的字符串使得任意一个前缀中1的数目不少于0的数目.

假设答案为f[n].边界条件为f[0]=1,表示没有括号/没有元素时也算有一种方案(空串也是一种合法序列).

插播两条高中数学:

分类加法计数原理:做一件事有m类方法,每类方法分别有A1,A2...Am种做法,那么做这件事共有\(A1+A2+...+Am\)种方法

分步乘法计数原理:做一件事有m个步骤,每个步骤分别有A1,A2...Am种做法,那么做这件事共有\(A1*A2*...*Am\)种方法

好了,接下来我们来将所学的用于实践.

考虑最左侧的左括号匹配的右括号在什么位置.假设这个左括号和匹配的右括号之间有2i个括号(这个数目必须是偶数),这2i个括号排列成合法括号序列的方案数为f[i].匹配的右括号右边还有2n-2i-2个括号,将它们排列为合法括号序列的方案数为f[n-i-1],这两部分可以认为是两个步骤,是独立的,那么总的方案数是f[i]*f[n-i-1].

对于不同的i,我们可以认为是做一件事的不同种类的方法.

于是\(f[1]=f[0]*f[0],f[2]=f[1]*f[0]+f[0]*f[1],f[3]=f[0]*f[2]+f[1]*f[1]+f[2]*f[0]\),这是一个O(n^2)的计算方式.

这里我们得到的f[n]也叫Catalan数(卡特兰数),它还具有很多实际意义.

紫书330~331页给出了Catalan数的另一个实际意义:多边形三角剖分数目,并通过另一个O(n^2)的递推公式,推倒了O(n)的递推公式.

另一个常用的计算公式是f[n]=C(2n,n)/(n+1)=C(2n,n) - C(2n,n-1),C(2n,n)为组合数.

时间: 2024-10-29 19:06:32

Catalan数,括号序列和栈的相关文章

括号序列(栈)

题目描述 Description 定义满足以下规则字符串为规则序列,否则不是规则序列: 1.空序列是规则序列: 2.如果S是规则序列,那么(S),[S],{S}和<S>也是规则序列: 3.如果A和B都是规则序列,那么AB也是规则序列. 例如,下面的字符串都是规则序列: (),[],(()),([]),()[],()[()],{{}}<>,([]<>{{}}),<<{}>> 而以下几个则不是: (,[,],)(,()),([(),<<,

(转载)Catalan数——卡特兰数

Catalan数--卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1)=1,Catalan数满足递归式:h(n) = h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1),n>=2该递推关系的解为:h(n) = C(2n-2,n-1)/n,n=1,2,3,...(其中C(2n-2,n-1)表示2n-2个中取n-1个的组合数) 问题描

Catalan数 &amp;&amp; 【NOIP2003】出栈序列统计

令h(1)=1, h(0)=1,catalan数满足递归式: h(n)=h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)h(0) (n>=2) =C(2n, n)/(n+1) =h(n-1)*2(2n-1)/(n+1) 具体推导请百度,这里只需记得推导公式为h(n)=h(n-1)*2(2n-1)/(n+1)即可. 我们来说说这个的应用吧,从catalan数的定义递归定义可以看出,它是由自己 本身的一部分和n减去一部分 的和得到的,也就是说,有n个物品,1个物品进行操作1,n-

codevs 1086 栈(Catalan数)

题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要性不言自明,任何一门数据结构的课程都会介绍栈.宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙 宁宁考虑的是这样一个问题:一个操作数序列,从1,2,一直到n(图示为1到3的情况),栈A的深度大于n. 现在可以进行两种操作, 1.将一个数,从操

[Catalan数]1086 栈、3112 二叉树计数、3134 Circle

1086 栈 2003年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). 栈的重要性不言自明,任何一门数据结构的课程都会介绍栈.宁宁同学在复习栈的基本概念时,想到了一个书上没有讲过的问题,而他自己无法给出答案,所以需要你的帮忙 宁宁考虑的

括号序列计数 数形结合 卡特兰数

问长度为 2n 的括号序列有多少个. 以 ( 的数量为 x 轴, ) 的数量为 y 轴, 建立坐标系. 初始状态对应 (0, 0) . 假设当前在 (x, y) , 如果下一位为 ( , 那么转移到 (x, y) + (1, 0) , 否则转移到 (x, y) + (0, 1) . 现在要求不超过 y = x 的从 (0, 0) 到 (n, n) 的路径数. 我们考虑用从 (0, 0) 到 (n, n) 的总的路径数, 减去非法的路径数. 总的路径数为 $\binom{2n}{n}$ . 对于非

特殊计数序列——Catalan数

Catalan数 前10项 \(1,1,2,5,14,42,132,429,1430,4862\) (注:从第\(0\)项起) 计算式 \(C_n=\frac{1}{n+1}\dbinom{2n}{n}\) \(C_{n+1}=\sum_{i=0}^nC_iC_{n-i}\) \(C_n=\dbinom{2n}{n}-\dbinom{2n}{n-1}\) \(C_n=\frac{4n-2}{n+1}C_{n-1}\) 组合意义 1.由\(n\)个\(+1\)和\(n\)个\(-1\)构成的\(2

【64测试20161112】【Catalan数】【数论】【扩展欧几里得】【逆】

Problem: n个人(偶数)排队,排两行,每一行的身高依次递增,且第二行的人的身高大于对应的第一行的人,问有多少种方案.mod 1e9+9 Solution: 这道题由1,2,5,14 应该想到Catalan数,但是我却花了两个小时去找递推式. 首先 Catalan数 : 基本规律:1,2,5,14,42,132,.......... 典型例题: 1.多边形分割.一个多边形分为若干个三角形有多少种分法. C(n)=∑(i=2...n-1)C(i)*C(n-i+1) 2.排队问题:转化为n个人

Catalan数——卡特兰数

一.Catalan数的定义 令h(0)=1,h(1)=1,Catalan数满足递归式:h(n) = h(0)*h(n-1) + h(1)*h(n-2) + ... + h(n-1)*h(0)  (n>=2) 该递推关系的解为:h(n) = C(2n,n)/(n+1),n=0,1,2,3,... (其中C(2n,n)表示2n个物品中取n个的组合数) 二.问题描述 12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种? 问题分析: 我们先把这12个