一,问题描述

给定一个以字符串形式表示的入栈序列,请求出一共有多少种可能的出栈顺序?如何输出所有可能的出栈序列?

比如入栈序列为: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);
}
}

思路②:直接求出合法的出栈序列。【而不是像思路①那样:先求出所有可能的出栈序列(求全排列),然后再找出合法的出栈序列。】

待完成。

四,参考资料

JAVA求解全排列

出栈顺序(卡特兰数)

可能的出栈顺序

出栈顺序 与 卡特兰数(Catalan)的关系的更多相关文章

  1. vijos - P1122出栈序列统计 (卡特兰数)

    P1122出栈序列统计 未递交 标签:NOIP普及组2003[显示标签] 描写叙述 栈是经常使用的一种数据结构,有n令元素在栈顶端一側等待进栈,栈顶端还有一側是出栈序列. 你已经知道栈的操作有两·种: ...

  2. SDUT 1266 出栈序列统计(卡特兰数)

    这道题是回溯算法,网上一查是卡特兰数先占上代码,题解过两天会写. #include <bits/stdc++.h> using namespace std; int main() { // ...

  3. Catalan数与出栈顺序个数,Java编程模拟

    问题描述: 队列中有从1到7(由小到大排列)的7个整数,问经过一个整数栈后,出栈的所有排列数有多少?如果整数栈的容量是4(栈最多能容纳4个整数),那么出栈的排列数又是多少? 分析:对于每一个数字i, ...

  4. n个元素进栈,共有多少种出栈顺序?

    1.基于栈的问题分析 我们把n个元素的出栈个数的记为f(n), 那么对于1,2,3, 我们很容易得出:                                   f(1) = 1     / ...

  5. 卡特兰数 Catalan数 ( ACM 数论 组合 )

    卡特兰数 Catalan数 ( ACM 数论 组合 ) Posted on 2010-08-07 21:51 MiYu 阅读(13170) 评论(1)  编辑 收藏 引用 所属分类: ACM ( 数论 ...

  6. 卡特兰数 catalan number

    作者:阿凡卢 出处:http://www.cnblogs.com/luxiaoxun/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留 ...

  7. 【讲●解】火车进出栈类问题 & 卡特兰数应用

    火车进出栈类问题详讲 & 卡特兰数应用 引题:火车进出栈问题 [题目大意] 给定 \(1\)~\(N\) 这\(N\)个整数和一个大小无限的栈,每个数都要进栈并出栈一次.如果进栈的顺序为 \( ...

  8. N个数依次入栈,出栈顺序有多少种

    题目:N个数依次入栈,出栈顺序有多少种? 首先介绍一下卡特兰数:卡特兰数前几项为 : 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 2 ...

  9. 浅谈卡特兰数(Catalan number)的原理和相关应用

    一.卡特兰数(Catalan number) 1.定义 组合数学中一个常出现在各种计数问题中出现的数列(用c表示).以比利时的数学家欧仁·查理·卡特兰的名字来命名: 2.计算公式 (1)递推公式 c[ ...

随机推荐

  1. 自己站点的nginx 配置信息

    user www www; worker_processes auto; error_log /home/wwwlogs/nginx_error.log crit; pid /usr/local/ng ...

  2. zabbix 使用问题两个--中文乱码,以及监控ESXi下的虚拟机

    1. 中文乱码 最开始中文显现 长方形不显示文字.解决办法: c:\windows\fonts 下面复制 楷体的字体(字体随意看自己喜欢) 文件名一般为: simkai.ttf 2.将simkai.t ...

  3. Test Scenarios for a window

    1 check if default window size is correct2 check if child window size is correct3 check if there is ...

  4. jmeter创建高级测试计划

    如果应用程序使用重写地址而不是使用cookie存储信息,需要做一些额外的工作去测试程序 为了正确的响应重写地址,jmeter 需要解析 从服务器获取html 并且检索会话ID, 1 合理利用pre-p ...

  5. Delphi中统一显示表格字段名的高效方法

    问题描述:在开发数据库程序时,我们经常要使用很多的表格显示组件DBGrid.当DBGrid显示某表格的数据时,其字段标题默认的就是后台数据库中的表格的字段名称.而为了数据库开发方便,后台数据库中的表格 ...

  6. 【Spring】—— 自动装配

    一.Spring中装配bean的方式 1.在XML中显式配置 2.在Java中进行显式配置 3.隐士的bean发现机制和自动装配 二.自动装配示例 1.在需要装配到其他bean中的类中加入@Compo ...

  7. CSS兼容性详解

    前面的话 对于前端工程师来说,不想面对又不得不面对的一个问题就是兼容性.在几年之前,处理兼容性,一般地就是处理IE低版本浏览器的兼容性.而近几年,随着移动端的发展,工程师也需要注意手机兼容性了.本文将 ...

  8. BZOJ2724 [Violet]蒲公英(分块)

    区间众数.分块,预处理任意两块间所有数的众数,和每块中所有数的出现次数的前缀和.查询时对不是整块的部分暴力,显然只有这里出现的数可能更新答案.于是可以优美地做到O(n√n). #include< ...

  9. HDU-1686-KMP-水题

    纯KMP #include <cstdio> #include <algorithm> #include <cstring> #include <ctype. ...

  10. day30 hashlib模块

    hashlib 提供摘要算法 最常见的就是MD5,当然一般来说MD5已经被足够了 不管算法多不一样,但是摘要的功能是不变的 对于相同的字符串进行摘要,使用同一个算法得到的值总是不变的 不同算法的话,会 ...