出栈顺序 与 卡特兰数(Catalan)的关系
一,问题描述
给定一个以字符串形式表示的入栈序列,请求出一共有多少种可能的出栈顺序?如何输出所有可能的出栈序列?
比如入栈序列为:1 2 3 ,则出栈序列一共有五种,分别如下:1 2 3、1 3 2、2 1 3、2 3 1、3 2 1
二,问题分析
先介绍几个规律:
①对于出栈序列中的每一个数字,在它后面的、比它小的所有数字,一定是按递减顺序排列的。
比如入栈顺序为:1 2 3 4。
出栈顺序:4 3 2 1是合法的,对于数字 4 而言,比它小的后面的数字是:3 2 1,且这个顺序是递减顺序。同样地,对于数字 3 而言,比它小的后面的数字是: 2 1,且这个顺序是递减的。....
出栈顺序:1 2 3 4 也是合法的,对于数字 1 而言,它后面没有比它更小的数字。同样地,对于数字 2 而言,它后面也没有比它更小的数字。
出栈顺序:3 2 4 1 也是合法的,对于数字 3 而言,它后面比 3 小的数字有: 2 1,这个顺序是递减的;对于数字 2 而言,它后面的比它 小的数字只有 1,也算符合递减顺序;对于数字 4 而言,它后面的比它小的数字也只有1,因此也符合递减顺序。
出栈顺序:3 1 4 2 是不合法的,因为对于数字 3 而言,在3后面的比3小的数字有:1 2,这个顺序是一个递增的顺序(1-->2)。
因此,当给定一个序列时,通过这个规律 可以轻松地判断 哪些序列是合法的,哪些序列是非法的。
②给定一个入栈顺序:1 2 3 .... n,一共有多少种合法的出栈顺序?参考:百度百科卡特兰数
答案是 卡特兰数。即一共有:h(n)=c(2n,n)/(n+1) 种合法的出栈顺序。
如果仅仅只需要求出一共有多少种合法的出栈顺序,其实就是求出组合 C(2n,n)就可以了。而求解C(2n,n),则可以用动态规划来求解,具体可参考: 排列与组合的一些定理
三,代码实现
给定一个入栈顺序,比如 1 2 3 ,如何输出所有可能的出栈顺序?
思路①:先求出入栈顺序的所有排列(即全排列),并将排列保存到一个LinkedList<String>中,然后依次遍历每一个序列,判断该序列是否是合法的序列。
所谓合法的序列,就是满足上面的规律1:对于出栈序列中的每一个数字,在它后面的、比它小的所有数字,一定是按递减顺序排列的。 关于如何求解一个序列的全排列,可参考:JAVA求解全排列
完整代码实现如下:(实现得不好,感觉比较复杂)
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList; public class AllStackPopOrder { public static LinkedList<String> allPermutation(String str){
if(str == null || str.length() == 0)
return null;
//保存所有的全排列
LinkedList<String> listStr = new LinkedList<String>(); allPermutation(str.toCharArray(), listStr, 0); //print(listStr);//打印全排列
return listStr;
} private static void allPermutation(char[] c, LinkedList<String> listStr, int start){ if(start == c.length-1)
listStr.add(String.valueOf(c));
else{
for(int i = start; i <= c.length-1; i++)
{
//只有当没有重叠的字符 才交换
if(!isSwap(c, start, i))
{
swap(c, i, start);//相当于: 固定第 i 个字符
allPermutation(c, listStr, start+1);//求出这种情形下的所有排列
swap(c, start, i);//复位
}
}
}
} private static void swap(char[] c, int i, int j){
char tmp;
tmp = c[i];
c[i] = c[j];
c[j] = tmp;
} private static void print(LinkedList<String> listStr)
{
Collections.sort(listStr);//使字符串按照'字典顺序'输出
for (String str : listStr) {
System.out.println(str);
}
System.out.println("size:" + listStr.size());
} //[start,end) 中是否有与 c[end] 相同的字符
private static boolean isSwap(char[] c, int start, int end)
{
for(int i = start; i < end; i++)
{
if(c[i] == c[end])
return true;
}
return false;
} public static LinkedList<String> legalSequence(LinkedList<String> listStr){
Iterator<String> it = listStr.iterator();
String currentStr;
while(it.hasNext())//检查全排列中的每个序列
{
currentStr = it.next();
if(!check(currentStr))
it.remove();//删除不符合的出栈规律的序列
}
return listStr;
}
//检查出栈序列 str 是否 是合法的出栈 序列
private static boolean check(String str){
boolean result = true;
char[] c = str.toCharArray();
char first;//当前数字.
int k = 0;//记录 compare 数组中的元素个数
char[] compare = new char[str.length()];
for(int i = 0; i < c.length; i++)
{
first = c[i];
//找出在 first 之后的,并且比 first 小的数字
for(int j = i+1; j < c.length; j++)
{
if(c[j] > first)
continue;
else
{
compare[k++] = c[j];//将比当前数字小的 所有数字 放在compare数组中
}
}
if(k == 0)
continue;
else{
for(int m = 0; m < k-1; m++)//判断 compare 数组是否是 递减的顺序
{
if(compare[m] < compare[m+1])
{
result = false;//不符合递减顺序
return result;
}
}
}
k=0;
}
return result;
} //hapjin test
public static void main(String[] args) {
String str = "1234";
LinkedList<String> listStr = legalSequence(allPermutation(str));
print(listStr);
}
}
思路②:直接求出合法的出栈序列。【而不是像思路①那样:先求出所有可能的出栈序列(求全排列),然后再找出合法的出栈序列。】
待完成。
四,参考资料
出栈顺序 与 卡特兰数(Catalan)的关系的更多相关文章
- vijos - P1122出栈序列统计 (卡特兰数)
P1122出栈序列统计 未递交 标签:NOIP普及组2003[显示标签] 描写叙述 栈是经常使用的一种数据结构,有n令元素在栈顶端一側等待进栈,栈顶端还有一側是出栈序列. 你已经知道栈的操作有两·种: ...
- SDUT 1266 出栈序列统计(卡特兰数)
这道题是回溯算法,网上一查是卡特兰数先占上代码,题解过两天会写. #include <bits/stdc++.h> using namespace std; int main() { // ...
- Catalan数与出栈顺序个数,Java编程模拟
问题描述: 队列中有从1到7(由小到大排列)的7个整数,问经过一个整数栈后,出栈的所有排列数有多少?如果整数栈的容量是4(栈最多能容纳4个整数),那么出栈的排列数又是多少? 分析:对于每一个数字i, ...
- n个元素进栈,共有多少种出栈顺序?
1.基于栈的问题分析 我们把n个元素的出栈个数的记为f(n), 那么对于1,2,3, 我们很容易得出: f(1) = 1 / ...
- 卡特兰数 Catalan数 ( ACM 数论 组合 )
卡特兰数 Catalan数 ( ACM 数论 组合 ) Posted on 2010-08-07 21:51 MiYu 阅读(13170) 评论(1) 编辑 收藏 引用 所属分类: ACM ( 数论 ...
- 卡特兰数 catalan number
作者:阿凡卢 出处:http://www.cnblogs.com/luxiaoxun/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留 ...
- 【讲●解】火车进出栈类问题 & 卡特兰数应用
火车进出栈类问题详讲 & 卡特兰数应用 引题:火车进出栈问题 [题目大意] 给定 \(1\)~\(N\) 这\(N\)个整数和一个大小无限的栈,每个数都要进栈并出栈一次.如果进栈的顺序为 \( ...
- N个数依次入栈,出栈顺序有多少种
题目:N个数依次入栈,出栈顺序有多少种? 首先介绍一下卡特兰数:卡特兰数前几项为 : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 2 ...
- 浅谈卡特兰数(Catalan number)的原理和相关应用
一.卡特兰数(Catalan number) 1.定义 组合数学中一个常出现在各种计数问题中出现的数列(用c表示).以比利时的数学家欧仁·查理·卡特兰的名字来命名: 2.计算公式 (1)递推公式 c[ ...
随机推荐
- apache自带压力测试工具ab的使用及解析
当你搭建了apache服务器并在上面部署了web网站,在网站运行前,为了使apache服务器的性能得到更好的应用,我们可以先对其进行压力测试.进行压力测试其实非常简单,我们也不用再额外下载安装什么测试 ...
- 《ERP系统修正数据的sql文件》
第一 1.修正销售客户创建者的sql脚本: UPDATE e_sales_customers sc SET sc.user_id = ( SELECT tmp.user_id FROM ( SELEC ...
- POJ2635-The Embarrassed Cryptographer-大整数素因子
计算一个大整数(10^100)中有没有一个小于L的素因子.这个大整数是两个素数的乘积.其实就是RSA加密. 做法是把大整数表示成千进位,用数组存储,然后一位一位地取模. /*------------- ...
- hdu1176 (免费馅饼)
免费馅饼 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- mysql 计算两个日期之间的工作日天数
创建透视表t500 建表 CREATE TABLE `t500` ( `id` int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) ) ENGINE ...
- 自学Linux Shell3.5-目录处理命令mkdir rmdir
点击返回 自学Linux命令行与Shell脚本之路 3.5-目录处理命令mkdir rmdir 1. mkdir命令 创建一个或多个新的目录. mkdir 命令创建由 Directory 参数指定的一 ...
- NOIP2012题解
NOIP2012题解 Day1 Vigenère 密码 vigenere 直接模拟就好了,对于那张表找找规律就很短了. #include<iostream> #include<cst ...
- Spring实现文件的上传下载
背景:之前一直做的是数据库的增删改查工作,对于文件的上传下载比较排斥,今天研究了下具体的实现,发现其实是很简单.此处不仅要实现单文件的上传,还要实现多文件的上传. 单文件的下载知道了,多文件的下载呢? ...
- typescript变量声明(学习笔记非干货)
var a=10; function f(){ var message="hello,world"; return message; } function f(){ a=10; r ...
- react中实现点击跳转到新页面方法
实现点击跳转到新页面,可以有两种形式,一个是本地页面打开,一个是本地页面不变跳转到新的页面. (一)页面点击本地页面打开新页面 引入ant的Button组件 <Button style={{ba ...