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

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

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

栈中的元素遵循后进先出(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数,括号序列和栈的更多相关文章

  1. 洛谷 P1241 括号序列(栈)

    嗯... 题目链接:https://www.luogu.org/problem/P1241 首先这道题是栈的入门题的加强版, 不仅要你判断这个括号序列是否合法,还要你将这个序列补充完整... 一开始是 ...

  2. catalan 数——卡特兰数(转)

    Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...

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

    Catalan数——卡特兰数 今天阿里淘宝笔试中碰到两道组合数学题,感觉非常亲切,但是笔试中失踪推导不出来后来查了下,原来是Catalan数.悲剧啊,现在整理一下 一.Catalan数的定义令h(1) ...

  4. 12个高矮不同的人,排成两排(catalan数)

    问题描述: 12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种? 这个笔试题,很YD,因为把某个递归关系隐藏得很深. 问题分析: 我们先把这12个 ...

  5. 2020牛客寒假算法基础集训营4 B:括号序列

    B : 括号序列 考察点 : 栈 坑点 : 只有栈空时才是合法的 Code: #include <stack> #include <cstdio> #include <s ...

  6. 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) ...

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

    1086 栈 2003年NOIP全国联赛普及组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 栈是计算机中 ...

  8. codevs 1086 栈(Catalan数)

    题目描述 Description 栈是计算机中经典的数据结构,简单的说,栈就是限制在一端进行插入删除操作的线性表. 栈有两种最重要的操作,即pop(从栈顶弹出一个元素)和push(将一个元素进栈). ...

  9. luogu P1044 火车进出栈问题(Catalan数)

    Catalan数就是魔法 火车进出栈问题即: 一个栈(无穷大)的进栈序列为 1,2,3,4,...,n 求有多少个不同的出栈序列? 将问题进行抽象, 假设'+'代表进栈, 则有'-'代表出栈 那么如果 ...

随机推荐

  1. 20145209 实验二 《Java面向对象程序设计》 实验报告

    20145209 实验二 <Java面向对象程序设计> 实验报告 实验内容 1.初步掌握单元测试和TDD. 2.理解并掌握面向对象三要素:封装.继承.多态. 3.初步掌握UML建模. 4. ...

  2. Android开发笔记——图片缓存、手势及OOM分析

    把图片缓存.手势及OOM三个主题放在一起,是因为在Android应用开发过程中,这三个问题经常是联系在一起的.首先,预览大图需要支持手势缩放,旋转,平移等操作:其次,图片在本地需要进行缓存,避免频繁访 ...

  3. 第五章Web应用与应用层协议

    Web应用与应用层协议 本篇博文中的主要参考文献是<计算机网络高级教程>,分别是吴功宜老先生和吴英教授合著.这部教程是我研究生老师所推荐的网络必读科目,由于该教程讲解的基础知识详细,但内容 ...

  4. Python中abs()和math.fabs()区别

    描述:Python中fabs(x)方法返回x的绝对值.虽然类似于abs()函数,但是两个函数之间存在以下差异: abs()是一个内置函数,而fabs()在math模块中定义的. fabs()函数只适用 ...

  5. Red Hat Enterprise Linux / CentOS 7 yum安装zabbix4.0

    添加Zabbix存储库安装存储库配置包. 该软件包包含yum(软件包管理器)配置文件. rpm -ivh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_6 ...

  6. clone中的浅复制和深复制

    clone:用于两个对象有相同的内容时,进行复制操作. 提示:Java中要想自定义类的对象可以被复制,自定义类就必须实现Cloneable中的clone()方法. 浅复制:另一个对象用clone()方 ...

  7. windows下对python的pip更新到最新版本

    1->打开windows的命令窗口. 2->进入到pip.exe所在的文件夹下,我安装的python在G:\python3.6文件夹下,pip.exe则在G:\python3.6\Scri ...

  8. 简析Monte Carlo与TD算法的相关问题

    Monte Carlo算法是否能够做到一步更新,即在线学习? 答案显然是不能,如果可以的话,TD算法还有何存在的意义?MC算法必须要等到episode结束后才可以进行值估计的主要原因在于对Return ...

  9. JUnit initializationError错误

    一.JUnit Test 测试 initializationError错误 MyMaincom.test.sunc.MyMaininitializationError(com.test.sunc.My ...

  10. Python爬虫入门(6):Cookie的使用

    为什么要使用Cookie呢? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓 ...