面试 16:栈的压入压出队列(剑指 Offer 第 22 题)

我们今天继续来看看周五留下的习题:

面试题:输入两个整数序列,第一个序列表示栈的压入顺序,请判断二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如:压入序列为{1,2,3,4,5},那{4,5,3,2,1} 就是该栈的弹出顺序,而{4,3,5,1,2} 明显就不符合要求;

这道题还是比较容易想到思路,很直观的想法就是建立一个辅助栈,把输入的第一个序列中的数字依次压入该辅助栈,并按照第二个序列的顺序依次从该栈中弹出数字。

提前想好测试用例

一样是老方法,我们先准备测试用例:

传入两个 null,或者 1 个 null,或者空数组,此时应该不符合要求;

传入两个不相等的数组,应该直接不符合要求;

分别传入题干的示意值,他们应该分别满足和不满足要求;

传入单个数字,选择一组满足要求的和一组不满足要求的;

思考程序逻辑

判断一个序列是不是栈的弹出序列的规律:如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。如果所有的数字都压入栈了仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。

然而有的小伙伴还是容易被绕晕,这时候不妨我们可以直接作一个表格来模拟他们的压栈出栈过程,数据就采用我们题设中的数据吧~

用作图和模拟数据更容易给面试官一个你是个喜欢思考的好同事哟~

首先看看我们正确的数据。

判断操作 操作 栈 弹出数字
栈没数据,push 数组还有数据、压入   压入   1      
栈顶是 1,不等于pop[0],push 数组还有数据、压入   压入   1、2      
栈顶是 2,不等于pop[0],push 数组还有数据、压入   压入   1、2、3      
栈顶是 3,不等于pop[0],push 数组还有数据、压入   压入   1、2、3、4      
栈顶是 4,等于pop[0],弹出数字 4   弹出   1、2、3   4  
栈顶是 3,不等于pop[1],push 数组还有数据、压入   压入   1、2、3、5      
栈顶是 5,等于pop[1],弹出数字 5   弹出   1、2、3   5  
栈顶是 3,等于pop[2],弹出数字 3   弹出   1、2   3  
栈顶是 2,等于pop[3],弹出数字 2   弹出   1   2  
栈顶是 1,等于pop[4],弹出数字 1   弹出       1  

实际上我们在草稿纸上并不需要做这么标准的表格,只要能表现意思即可。

我们仔细观察可以得知,我们判断压入还是弹出甚至是得出确定结论的标准是,先看当前栈顶元素和弹出的数字是否相等,如果相等则直接弹出;如果不相等则直接看看压入数组中还有没有元素,如果有则直接压入到辅助栈;如果已经没有数据则代表第二个序列不是第一个序列的弹出栈。

编写程序代码

实际上我们心中已经大概知道怎么写了。

private static boolean isPushStack(int[] push, int[] pop) { if (push == null || pop == null || pop.length != push.length) return false; Stack<Integer> stack = new Stack<>(); int j = 0; for (int i = 0; i < pop.length; i++) { // 第一步判断栈顶元素是否和 pop[i] 相等 if (!stack.isEmpty() && pop[i] == stack.peek()) { // 如果相等则直接 pop() stack.pop(); } else { // 栈顶和 pop[i] 不相等,则判断 push 数组还有没有数据 // 如果 push 数组没数据了,栈顶元素又不等于 pop[i],则说明不符合要求 if (j == push.length) return false; while (j < push.length) { // 如果还有数据,则直接 push stack.push(push[j]); ++j; // push 后继续判断栈顶元素是否和 pop[i] 相等; if (pop[i] == stack.peek()) { // 如果相等则弹出栈,并且推出内层循环 stack.pop(); break; } } } } return true; } 验证测试用例

写毕代码后,我们得用自己事先准备的测试用例测试一下。

测试 1 和测试 2 我们已经考虑到了,这样的情况直接在功能之前就判断,不符合条件的直接返回 false,测试通过。

传入{1,2,3,4,5} 和 {4,5,3,2,1}:

进入循环,i = 0,pop[i] = 4,直接进入 else 语句,开始 push 数据,一直 push 到 j = 3。

此时栈内元素为 {1,2,3,4},push 里面还剩下 {5}。因为 pop[0] 等于栈顶,所以进入 if 语句,弹出 4,退出 while 循环;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwdss.html