已知n个数的入栈序列,求一共有多少种出栈序列 (卡特兰数)
已知\(n\)个数的入栈序列,求一共有多少种出栈序列
这个经典问题有两种解法。
解法一:
设\(f(x)\)为\(x\)个数入栈后,再全部出栈的序列数量
假设我们有\(4\)个数\(a,b,c,d\), 我们来看\(a\)的出栈顺序.
假如\(a\)第一个出栈,那么后面还有\(3\)个数没有出栈,因此方法数是\(f(3)\).
假设\(a\)第二个出栈,那么\(a\)的前面有\(1\)个数已经出栈,后面还有\(2\)个数没有出栈,因此方法数为\(f(1) * f(2)\).
假设\(a\)第三个出栈,那么\(a\)的前面有\(2\)个数已经出栈,后面还有\(1\)个数没有出栈,因此方法数为\(f(2) * f(1)\).
同理,\(a\)第四个出栈的方法数为\(f(3)\).
那么我们就可以得到\(f(4) = f(3) + f(1) *f(2) + f(2)*f(1) +f(3)\).
对于\(n\)来推广一下,可以得到:\(f(n)=\sum_{i=1}^{n}f(i - 1)*f(n-i)\).
不难发现这就是卡特兰数,这里就不在赘述了。
解法二:
我们假设\(-1\)表示出栈,\(1\)表示入栈,这样我们就可以用\(-1\)和\(1\)组成的序列来表示出入栈操作。
首先来限定一些条件,一个合法的序列\(0\)和\(1\)的数量一定是相等的。并且序列的前缀和一定是不小于\(0\)的。
了解了上面两个条件后,我们知道所有的序列数为\(C^{\ n}_{2n}\),因为\(-1\)和\(1\)的数量相同。在这\(C^{\ n}_{2n}\)个序列中,存在不合法的序列,即前缀和小于\(0\)的序列,我们想要知道这些不合法的序列有多少。
假设我们有一个序列\(1,-1,-1,1,-1,1\),这里在第三个下标,我们发现了它的前缀和小于\(0\),因此它不合法。再来推广一下,在这所有\(C^{\ n}_{2n}\)个序列中,不合法的序列它的前缀和一定在某一处小于\(0\).
接下来,我们将序列开头到不合法下标的这一段进行取反。首先拿上面的例子来进行说明,取反后得到:\(-1,1,1,1,-1,1\),不难发现,现在得到的序列\(+1\)比\(-1\)多出一个.
现在再来进行推广,我们截取的不合法序列段(从开头到不合法前缀和下标),这一段中的\(-1\)一定比\(+1\)多一个,那么将这一段取反后所得到的总序列中的\(+1\)一定比\(-1\)多一个。
不难发现,不合法的序列一定对应唯一一个取反后的序列,并且取反后的序列中\(+1\)有\(n+1\)个,\(-1\)有\(n-1\)个,那么根据这个条件,我们就可以得到所有不合法的序列数量为\(C_{2n}^{n+1}\)或者\(C^{n-1}_{2n}\)(因为他两相等)。
最后,合法的序列数为:\(C^{\ n}_{2n}-C_{2n}^{n+1\ or\ n-1}\).
这个解法的关键在于,不合法的序列一定唯一对应一个取反后的序列,那么我们可以算出所有取反后的数列有多少种(根据\(+1\)有\(n+1\)个,\(-1\)有\(n-1\)个的性质),来对应出不合法的序列数,从而得到答案.
因为感觉这种解法非常的巧妙,因此想写篇博客来总结一下.
已知n个数的入栈序列,求一共有多少种出栈序列 (卡特兰数)的更多相关文章
- n个元素的入栈顺序有多少种出栈顺序?
问题:w1.w2.w3.w4.w5,5个元素将会按顺序入栈,求出栈顺序有多少种情况. 先写一下结论方便记忆: 1个元素:1种 2个元素:2种 3个元素:5种 4个元素:14种 5个元素:42种 简单的 ...
- 找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
找出数组中出现次数超过一半的数,现在有一个数组,已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数 #include<iostream>using namespace s ...
- 求入栈顺序为1234……N的序列的所有可能的出栈序列
class Program { private static void Fun(int x, int n, Stack<int> stack, List<int> outLis ...
- 已知ip地址和其子网掩码如何求网络号子网号主机号
已知ip地址为10.130.89.95,其子网掩码为255.255.255.224,求其网络号.子网号和主机号. 要看子网掩码变长在第几节,255.255.255.224是在第四节借了位 把224转换 ...
- 已知空间三点组成的面求该面上某点的Z值
已知空间三点,那么可以就可以确定空间三点组成的平面.此时可以根据某一点的X值和Y值,来求取该点在平面上的Z值.这个过程对于求三角面片上某点的高程或者权值特别有用,其本身也可以看作一种线性插值. 其算法 ...
- DS Tree 已知先序、中序 => 建树 => 求后序
参考:二叉树--前序和中序得到后序 思路历程: 在最初敲的时候,经常会弄混preorder和midorder的元素位置.大体的思路就是在preorder中找到根节点(根节点在序列的左边),然后在mid ...
- poj 1363 Rails in PopPush City &&【求堆栈中合法出栈顺序次数】
问题如下: 问题 B: Rails 时间限制: Sec 内存限制: MB 提交: 解决: [提交][状态][讨论版] 题目描述 There is a famous railway station in ...
- n个元素进栈,共有多少种出栈顺序?
1.基于栈的问题分析 我们把n个元素的出栈个数的记为f(n), 那么对于1,2,3, 我们很容易得出: f(1) = 1 / ...
- c语言将2进制数转化为10进制数(栈的初始化,进栈,出栈)
//c语言描述 将2进制转化为10进制 #include <stdio.h> #include <stdlib.h> #include <math.h> #defi ...
- 已知一个数出现的次数超过了一半,请用O(n)的复杂度的算法找出这个数
#include<iostream> using namespace std; //#define maxn 2000010 #include<stdio.h> //int a ...
随机推荐
- K8s+Docker 学习笔记系列
学前知识 你需要掌握 Linux 的常用命令.你可以通过Linux 教程 来学习相关命令. Docker应用场景 Web 应用的自动化打包和发布. 自动化测试和持续集成.发布. 在服务型环境中部署和调 ...
- axel多线程下载
Axel 是一个轻量级下载程序,它和其他加速器一样,对同一个文件建立多个连接,每个连接下载单独的文件片段以更快地完成下载. Axel 通过打开多个 HTTP/FTP 连接来将一个文件进行分段下载,从而 ...
- APP 监听手机键盘是否弹出
/** * 监听键盘是否弹出 * @param show * @param hide */ export const addEventKeyboardStatus = (show,hide)=> ...
- 数据库结构差异比较-SqlServer
/****** Object: StoredProcedure [dbo].[p_comparestructure_2005] Script Date: 2022/10/8 10:00:20 **** ...
- 记录下老dropbox的使用
32-bit: wget -O - "https://www.dropbox.com/download?plat=lnx.x86" | tar xzf - 64-bit: wget ...
- DBeaver的使用
1.下载安装: https://dbeaver.io/download/ 2.下载后解压到指定目录,双击安装包: 然后 进行连接,在连接数据库的时候,会提示下载文件,下载的时候老是出错,选择强制下载就 ...
- Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hive.DELETEME1643159643943' doesn't exist
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'hive.DELETEME1643159643 ...
- 如何在 Apinto 实现 HTTP 与gRPC 的协议转换 (上)
什么是 gRPC 像gRPC是由google开发的一个高性能.通用的开源 RPC 框架,主要面向移动应用开发且基于HTTP/2协议标准而设计,同时支持大多数流行的编程语言. gRPC基于 HTTP/2 ...
- 工良出品:包教会,Hadoop、Hive 搭建部署简易教程
目录 导读 Hadoop.Hive 是什么 运行环境 Java 环境 Mysql 下载 Hadoop.Hive 和 驱动 安装 Hadoop core-site.xml hdfs-site.xml m ...
- 基于springboot实现SSM整合
(1)SpringBoot整合Spring(不存在) (2)SpringBoot整合SpringMVC(不存在) (3)SpringBoot整合MyBatis(主要) 一.新建springboot项目 ...