最近,翻回了一下数据结构的书,大三上的课,现在有些内容忘了。书的最后一章“数据结构的综合应用”里面有一道N列火车进出站的问题,把问题简化了,就是N个数进出栈的问题:即N个数有多少种不同的进出栈顺序(只考虑进栈和出栈的次序,不考虑数的大小,即N个“相同”的数)。
那时候,我是用穷举法来做的,即求出N个数的进出栈的全排列,删除存在某个位置之前进栈次数小于出栈次数的排列。现在重新想了一下,想到了自己分析过的一
道身高排队的题目:12个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
其实,这两个问题之前存在着一种巧妙的同构关系:在身高排队问题中,我们可以先把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代入即可求得总的排列数,但这样并不能求得具体的排列次序。我在网上搜索了一下,这类同构的问题还有不少,不过在求具体的排列次序的时候很少看到非穷举的解决方法,顺便向大家问一下还有没有其它非穷举的解法。
分享到:
相关推荐
在数据结构与算法领域,二叉树是一种常见的非线性数据结构,由节点组成,每个节点最多有两个子节点,分别称为左子节点和右子节点。在处理二叉树的各类问题时,分治法作为一种高效的策略被广泛应用。本篇文章将围绕...
图同构问题是指确定两个给定的图是否在本质上相同的问题。具体来说,如果存在一个双射映射将一个图中的顶点映射到另一个图的顶点,使得任意两个顶点之间的边关系保持不变,则称这两个图是同构的。从算法的角度来看,...
图论中的一个基础问题是图的同构性问题,即两个图是否在节点之间存在一一对应关系,使得它们具有相同的结构。CAD(计算机辅助设计)技术应用软件在判断图的同构性问题上具有一定的应用前景。 CAD技术是现代设计领域...
循环同构问题是字符串处理中的一个特殊问题,它涉及到两个字符串通过某种循环操作能够相互匹配。为了更高效地解决这一问题,科学家们开发出了一系列算法,包括枚举算法、匹配算法、KMP算法等。本文档是一份PPT学习...
首先,在方程的应用方面,如果两个表达式呈现同构特征,可以将其中一个看作另一个的特例。例如,当两个方程具有相同的结构时,可以尝试将其中一个解作为另一个方程的解,或者利用同构式对解的性质进行推导。这种方法...
而线性同构是指两个线性空间之间存在一种特殊的双射线性映射,保持了向量空间的结构特性。 首先,线性空间(向量空间)由一组向量构成,这些向量在加法运算和数乘运算下封闭,且满足八条公理,如加法交换律、结合律...
两个图(包括树)G和H被认为是同构的,如果存在一个一一对应关系φ,将G的节点映射到H的节点,使得G中任意两个节点u和v之间的边在H中由φ(u)和φ(v)之间存在,且边的方向和权重保持不变。对于树,这意味着如果两棵树...
循环同构指的是两个字符串经过循环移位后能够完全重合的性质。例如,字符串"abc"和"cab"在循环移位后都能重合,所以它们是循环同构的。这一部分的内容帮助学习者建立起对问题的基本认识。 随后,我们详细介绍了最小...
同构数(Isomorphic Number)是指两个数在不同进制下的表示形式相同。换句话说,如果一个数在十进制下的表示形式与在其他进制下的表示形式一致,那么它就是一个同构数。让我们通过一些例子来更好地理解同构数。例如...
在现代数学和计算机科学领域,群论和同构计数是两个非常重要的概念。群论是研究具有特定运算规则的集合的结构和性质的数学分支,而同构计数则是研究如何判断和计算两个结构之间的等价关系数量。为了深入理解这两个...
基于矩阵变换算法的图同构识别是判断两个无向图是否同构的重要方法,该算法可以通过矩阵变换来实现图同构识别。本资源摘要信息对基于矩阵变换算法的图同构识别进行了详细的知识点总结,为读者提供了一个系统的了解该...
同构数是指两个不同的数,在经过某种数学操作后,如模运算,可以相互对应。例如,在模5的情况下,数2和7是同构的,因为它们除以5的余数相同(都是2)。在更广义的上下文中,同构数可以扩展到更复杂的结构,如群和环...
分治法是一种重要的算法设计策略,其基本思想是将一个复杂的问题分解成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。在本例中,我们使用分治法来判断两棵...
《函数同构问题》主要探讨了函数在不同变换下的同构关系,以及如何利用这些关系解决各类不等式和方程的问题。以下是该主题的主要知识点: 1. **顺反同构**: - **顺同构**:通过平移和拉伸函数图形,保持其基本...
- 在方程中的应用:当两个方程具有同构特征时,即变量不同但其它部分相同,可以通过相互之间的关系来解决方程问题。 - 在不等式中的应用:同构特征的不等式可以转换为函数,利用函数的单调性质来比较大小或求解...
如果两个节点都不为空,那么需要比较它们的左右子树是否同构。有两种情况:左子树同右子树,或者左子树同右子树。因此,同构函数需要递归地调用自身去验证这些关系。 5. 主函数的逻辑:主函数中,首先调用BuildTree...