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)为组合数.
catalan数的一个推广:
n个左括号,m个右括号,任意前缀中左括号不少于右括号的序列数?答案是C(n+m,m)-C(n+m,m-1).
Catalan数,括号序列和栈的更多相关文章
- 洛谷 P1241 括号序列(栈)
嗯... 题目链接:https://www.luogu.org/problem/P1241 首先这道题是栈的入门题的加强版, 不仅要你判断这个括号序列是否合法,还要你将这个序列补充完整... 一开始是 ...
- catalan 数——卡特兰数(转)
Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...
- (转载)Catalan数——卡特兰数
Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...
- 12个高矮不同的人,排成两排(catalan数)
问题描述: 12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种? 这个笔试题,很YD,因为把某个递归关系隐藏得很深. 问题分析: 我们先把这12个 ...
- 2020牛客寒假算法基础集训营4 B:括号序列
B : 括号序列 考察点 : 栈 坑点 : 只有栈空时才是合法的 Code: #include <stack> #include <cstdio> #include <s ...
- Catalan数 && 【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) ...
- [Catalan数]1086 栈、3112 二叉树计数、3134 Circle
1086 栈 2003年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 栈是计算机中 ...
- codevs 1086 栈(Catalan数)
题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). ...
- luogu P1044 火车进出栈问题(Catalan数)
Catalan数就是魔法 火车进出栈问题即: 一个栈(无穷大)的进栈序列为 1,2,3,4,...,n 求有多少个不同的出栈序列? 将问题进行抽象, 假设'+'代表进栈, 则有'-'代表出栈 那么如果 ...
随机推荐
- elasticsearch对某段时间范围内按时间间隔进行统计
{ "query" : { "constant_score" : { "filter" : { "range" : { ...
- JS 中屏幕、浏览器和文档的高度、宽度和距离
1.各种对象 window.screen - 屏幕,window - 窗口,document.documentElement & document.body.parentNode - 文档,d ...
- Ansible开发之路
一.初识Ansible 链接:https://www.cnblogs.com/baishuchao/articles/9164083.html 二.Ansible的架构 链接:https://www. ...
- 使用Photon引擎进行unity网络游戏开发(四)——Photon引擎实现网络游戏逻辑
使用Photon引擎进行unity网络游戏开发(四)--Photon引擎实现网络游戏逻辑 Photon PUN Unity 网络游戏开发 网络游戏逻辑处理与MasterClient 网络游戏逻辑处理: ...
- join 中的on和where的区别
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表, 然后再将这张临时表返回给用户. 在使用left jion时,on和where条件的区别如下: 1.on条件是在生成临时表时使用的条 ...
- Right-BICEP 测试四则运算程序
测试方法: Right-BICEP 测试计划: 1.边界测试是否正确 2.负数表示是否实现 3.是否有乘除法 4.是否可以选择题目数量 5.是否有输出方式 6.是否有括号 7.是否有重复查询 ...
- iframe高度自适应的6个方法
原文链接:http://caibaojian.com/iframe-adjust-content-height.html JS自适应高度,其实就是设置iframe的高度,使其等于内嵌网页的高度,从而看 ...
- Java 数组转字符
public static String toString(int[] arr){ String temp = ""; for(int i = 0;i<arr.length; ...
- 玩下软工项目,第一轮--全局Context的获取,SQLite的建立与增删改查,读取用户通话记录信息
项目的Github地址:https://github.com/ggrcwxh/LastTime 采用基于git的多人协作开发模式 软件采用mvc设计模式,前端这么艺术的事我不太懂,交给斌豪同学去头疼了 ...
- Markdown的基本语法
Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的语法十分简单.常用的标记符号也不 ...