数据结构与算法--举例分析法- 栈的压入弹出序列
举例分析
- 与上两篇问中画图方法一样,我们可以用举例模拟的方法思考分析复杂问题。当一眼不能看出问题的规律的时候,我们可以用几个具体的例子来模拟一下问题的过程。这样就和我们在程序出现问题时候的debug一样,走一下整个流程,可以直观的看到整个过程。
- 具体的例子还能帮助我们确保代码的质量,在编码完成后,可以将例子当做测试用例来模拟运行,看每一步操作后的结果和我们预期的是不是一样的。
包含min方法的栈
- 题目:定义栈的数据结构,请在改类型中实现一个能够得到栈的最小元素min函数。在改栈中,调用min,push,pop的时间复杂度O(1)
- 此处与普通栈不同点在于需要知道每次栈变动时候最小值。并且难点在于O(1)的时间复杂度,我们第一反应是标记最小值,这样可以在O(1)时间得到最小元素。但是最小值出栈后,次小的值就变成最小值,此时是无法获取这个值
- 另外一个思路,每次入栈对栈中元素进行排序,这样能拿到最小值在栈首,会在尾。但是这样就违背了栈的后进先出的原则就不是栈了。
- 分析到此处发现一个栈A并不能解决问题,我们用一个辅助的栈空间B,每次添加一个元素到A时候,将添加元素与最小元素比较(临时变量保存最小元素),将最小元素添加到B,即使最小元素没有变化仍然重复添加到B占位用。我们用如下案例分析:
步骤 | 操作 | 数据栈A | 辅助栈B | 最小值 |
---|---|---|---|---|
1 | 压入3 | 3 | 3 | 3 |
2 | 压入6 | 3,6 | 3,3 | 3 |
3 | 压入4 | 3,6,4 | 3,3,3 | 3 |
4 | 压入45 | 3,6,4,45 | 3,3,3,3 | 3 |
5 | 压入0 | 3,6,4,45,0 | 3,3,3,3,0 | 0 |
6 | 压入2 | 3,6,4,45,0,2 | 3,3,3,3,0,0 | 0 |
如上表格,我们将最小元素每次都添加到辅助栈B中,就能保证辅助栈的栈顶是最小元素。
当最小元素从数据栈弹窗,我们同时操作辅助栈弹窗,这样保证辅助栈下一个值是最小值。
每一步操作数据栈,辅助站都同步,可以保证辅助栈顶永远都是数据栈中所有数据的最小值
实现方法是在之前文章数据结构与算法–简单栈实现及其应用基础上完成。实现如下:
/*** 包含min方法的栈实现* @author liaojiamin* @Date:Created in 16:02 2021/4/2*/
public class MyStackWithMin {private static MyStack dataStack = new MyStack();private static MyStack minStack = new MyStack();public static void push(int num){if(dataStack.size() == 0 && minStack.size() == 0){dataStack.push(num);minStack.push(num);}else {dataStack.push(num);if((int)minStack.getTop() > num){minStack.push(num);}else {minStack.push(minStack.getTop());}}}public static int pop(){if(dataStack.size() == 0 || minStack.size() == 0){return Integer.MAX_VALUE;}minStack.pop();return (int)dataStack.pop();}public static int min(){if(minStack.size() == 0){return Integer.MAX_VALUE;}return (int)minStack.pop();}public static void main(String[] args) {Random random = new Random();for (int i = 0; i < 100; i++) {int temp = random.nextInt(100);System.out.println(temp);push(temp);}System.out.println(min());}
}
栈的压入,弹出序列
- 题目:输入两个整数序列,第一个序列表示栈的压入顺序,判断第二个序列是否可能是栈的弹出顺序,假设入站的所有数字均不相等,例如:1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是可能的一个出栈,但是4,3,5,1,2就不可能是出栈的方式
- 我们依然用案例的方法分析,如下表格分析题中两种情况。
步骤 | 操作 | 栈 | 弹出数字 |
---|---|---|---|
1 | 压入1 | 1 | |
2 | 压入2 | 1,2 | |
3 | 压入3 | 1,2,3 | |
4 | 压入4 | 1,2,3,4 | |
5 | 弹出 | 1,2,3 | 4 |
6 | 压入5 | 1,2,3,5 | |
7 | 弹出 | 1,2,3 | 5 |
8 | 弹出 | 1,2 | 3 |
9 | 弹出 | 1 | 2 |
10 | 弹出 | 1 |
- 如上表格中每一个步骤操作,我们在第五步骤时候,弹出4,压入5,之后持续弹出,就能得到对应的弹出序列。
- 我们用同样的方式来递推第二个序列
步骤 | 操作 | 栈 | 弹出数字 |
---|---|---|---|
1 | 压入1 | 1 | |
2 | 压入2 | 1,2 | |
3 | 压入3 | 1,2,3 | |
4 | 压入4 | 1,2,3,4 | |
5 | 弹出 | 1,2,3 | 4 |
6 | 弹出 | 1,2 | 3 |
7 | 压入5 | 1,2,5 | |
8 | 弹出 | 1,2 | 5 |
9 | 下一个弹出的是1,但是1 不在栈顶,压栈序列已经都入栈,操作无法继续 |
- 如上两表格分析,入栈,出栈过程,我们可以判断一个序列是不是栈的弹出序列有如下规律:
- 如果下一个弹出的数字正好是栈顶数字,那么直接弹出
- 如果下一个弹出的数字不在栈顶,我们吧压栈序列中还没有入栈的数字压入辅助栈
- 持续压入直到下一个需要弹出的数字压入栈顶位置
- 如果所有数字都压入了栈但是还没找到下一个弹出的数字,那么该序列不存在一个弹出序列。
- 综上有如下实现:
/*** 存在栈A的入栈系列S,判断给出的序列B是否可能是A 的出序列,例如1,2,3,4,5 入栈,4,5,3,2,1 出栈* @author liaojiamin* @Date:Created in 16:54 2021/4/2*/
public class ValidateIsPopOrder {public static boolean validateIsPopOrder(int[] orderPush, int[] orderPop){if(orderPush == null || orderPop == null){return false;}if(orderPush.length != orderPop.length){return false;}MyStack myStack = new MyStack();int length = orderPop.length;int pushPosition = 0;int popPosition = 0;while (pushPosition < length || popPosition < length){while (myStack.size() > 0 && (int)myStack.getTop() == orderPop[popPosition] && popPosition < length){myStack.pop();popPosition++;}if(pushPosition < length){myStack.push(orderPush[pushPosition]);pushPosition ++;}if(pushPosition == length && myStack != null && (int)myStack.getTop() != orderPop[popPosition]){return false;}}return !(myStack.size() != 0);}public static void main(String[] args) {int[] push = {1,2,3,4,5};
// int[] pop = {4,5,3,2,1};
// int[] pop = {3,2,1,5,4};int[] pop = {4,3,5,1,2};System.out.println(validateIsPopOrder(push, pop));}
}
- 以上两个问题都是比较复杂的问题,并且需要多个步骤分析才能得出结果,初看时候很少有思路的,这个时候,我们通过举例分析,一步一步来看,当最后一步符合,或者卡在某一个步骤时候,我们此时往往能从当前的状态看出解题的思路。
上一篇:数据结构与算法–解决问题的方法-顺时针打印矩阵
下一篇:数据结构与算法–广度优先打印二叉树
数据结构与算法--举例分析法- 栈的压入弹出序列相关推荐
- 【剑指offer-Java版】22栈的压入弹出序列
栈的压入弹出序列:给定两个序列,一个是压入顺序,判断另外一个是否是该压入顺序的一个弹出顺序 思路:纯粹的模拟栈的压入和弹出顺序 分别遍历压栈序列seq1和另一个序列seq2 比较当前栈顶元素和seq2 ...
- 剑指offer-21.栈的压入弹出序列
1.题目 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...
- python 栈的压入弹出序列
| 栈的压入和弹出序列 输入两个整数序列,第一个序列表示栈的压入顺序, 请判断第二个序列是否为该栈的弹出顺序. 假设压入栈的所有数字均不相等. 例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序 ...
- 剑指offer 31.栈的、压入弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是 ...
- 算法笔记--简单实现栈的先入后出(FILO,First In Last Out)功能
算法笔记–简单实现栈的先入后出(FILO,First In Last Out)功能 stack 栈,是一个 先入后出(FILO,First In Last Out)的 有序列表,可以形象地理解为手枪的 ...
- 剑指Offer(Java实现)栈的压入、弹出序列
题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列 1,2,3,4,5 是某栈的压入顺序,序列 4,5,3,2,1 ...
- 举例让抽象问题具体化:栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一 ...
- 面试题整理6 栈的压入、弹出序列
<剑指offer>面试题22: 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出序列.假设压入栈的所有数字均不相同. 例如序列1.2.3.4.5是某栈的 ...
- 《剑指offer》-- 栈的压入与弹出序列、把字符串转化为整数、扑克牌顺子、孩子们的游戏(圆圈中最后剩下的数)
一.栈的压入与弹出序列: 1.题目: 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序. 假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序 ...
最新文章
- Python 3.8 新特性全面解读
- build-android-in-OS-X-Yosemite-Xcode-7
- python语法基础知识-python基础知识---简单语法
- 【UML 建模】UML建模语言入门 -- 静态图详解 类图 对象图 包图 静态图建模实战
- (47)逆向分析 KiSystemService 函数填充 _KTRAP_FRAME 部分
- 加强Eclipse代码自动提示的方法
- git 工具_Github开源工具分享之自托管GIT服务工具Gogs
- VistaDB 数据库,.NET的新选择
- java字符串常量池——字符串==比较的一个误区
- mysql数据库的字符集_mysql数据库中字符集乱码问题原因及解决
- PHP点歌插件,斗鱼弹幕点歌插件_小葫芦社区_小葫芦插件交流 - Powered by Discuz!
- java实现折半查找_java语言之实现折半查找算法
- 看完上汽制动的数字化,才发现以前的数据可视化大屏都白做了
- 计算机初级技能词,计算机领域英语常用词汇初级.doc
- Ubuntu 搭建SVN服务器(SVN Server)
- Python数据分析:数据可视化案例
- 计算机网络知识点及例题总结(五)数据链路层与局域网
- 开源项目 - 电子签章(移动端签名方案)
- 交叉编译Qt5.9.6
- 《机器学习》(周志华)线性回归