锁定老帖子 主题:两个同构问题的非穷举解法
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-01-14
最后修改:2010-01-15
最近,翻回了一下数据结构的书,大三上的课,现在有些内容忘了。书的最后一章“数据结构的综合应用”里面有一道N列火车进出站的问题,把问题简化了,就是N个数进出栈的问题:即N个数有多少种不同的进出栈顺序(只考虑进栈和出栈的次序,不考虑数的大小,即N个“相同”的数)。
其实,这两个问题之前存在着一种巧妙的同构关系:在身高排队问题中,我们可以先把12个高矮不同的人按身高从低到高排成一列,每次把队头的人选择放入第一排或是第二排的队尾,此时只要保证每次把人放入队尾的时候,第一排的人数不少于第二排即可,因为这样就保证了任何时候第二排的人一定第一排的高;而在N个数的进出栈问题中,假设N=12,则可以把进栈在整个操作中的次序(整个操作由进栈和出栈组成)放到身高排队问题中的第一排,相应地把出栈的次序放到第二排,保证任何时候第一排中的进栈次数不少第二排的出栈次数即可。
我修改了一下解决身高排队问题的代码,同样用非穷举的方法来解决这个问题: import java.util.Stack; public class PushPopStack { private int count = 0; private int total = 0; private Stack<Integer> pushOrders = new Stack<Integer>(); //存放进栈的次序 public PushPopStack(int total) { this.total = total; } private void printOrders() { for (int operOrder = 1, i = 0; operOrder <= total; operOrder++) { if (i < pushOrders.size() && pushOrders.get(i) == operOrder) { System.out.print("进 "); i++; } else { System.out.print("出 "); } } System.out.println(); } private void pushOrder(int order, int level) { pushOrders.push(order); if (level >= total / 2) { count++; printOrders(); // 打印一种进出栈顺序 pushOrders.pop(); return; } for (int i = order + 1; i < 2 * (level + 1); i++) pushOrder(i, level + 1); pushOrders.pop(); } public void pushPopOrder() { pushOrder(1, 1); System.out.println(total + " 个元素一共有 " + count + " 种不同的进出栈顺序。"); } public static void main(String[] args) { PushPopStack stack = new PushPopStack(12); stack.pushPopOrder(); } }
在我的博客中有篇“关于 阿里巴巴 身高排队问题的思考”的文章,里面有详细的分析解决过程 。其实,对于这两个问题还有一个便捷的求解方法,使用卡特兰公式 C(2n,n)/(n+1),把n=N/2代入即可求得总的排列数,但这样并不能求得具体的排列次序。我在网上搜索了一下,这类同构的问题还有不少,不过在求具体的排列次序的时候很少看到非穷举的解决方法,顺便向大家问一下还有没有其它非穷举的解法。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 1913 次