一、题目

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。

二、示例

2.1> 示例 1:

输入】pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出】true
解释】我们可以按以下顺序执行:push(1), push(2), push(3), push(4), pop() -> 4,push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

2.2> 示例 2:

输入】pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出】false
解释】1 不能在 2 之前弹出。

提示:

  • 0 <= pushed.length == popped.length <= 1000
  • 0 <= pushed[i], popped[i] < 1000
  • pushed 是 popped 的排列

三、解题思路

根据题目描述,我们会获得两个数组,一个是pushed数组,用于表示待入栈的元素及其入栈顺序;另一个是popped数组,表示出栈时元素的顺序。那么我们就可以通过这两个数组来模拟一下入栈和出栈的操作,那么如果执行完全部操作后,堆栈中已经没有任何元素的,则表示是符合题意的,我们就返回true;否则的话,我们就返回false了

那么根据以上的分析,我们需要创建一个堆栈数据结构,那么通常我们会选择Deque这个双向队列来模拟堆栈操作,当然也是可以选择Stack的,只是在提交后的执行效率会降低不少。

具体处理流程是这样的:我们创建指针j,指向popped数组的头部元素;然后从头开始遍历pushed数组;假设我们获取了pushed数组中的一个元素A,然后先将其放到堆栈中,之后进行如下判断逻辑:

栈顶元素等于popped[j] 】将栈顶元素弹出堆栈,并且将j指针向后移动一位(j++),重复执行这个操作,直到堆栈为空或者栈顶元素与popped[j]不同;
栈顶元素不等于popped[j] 】则不用做其他操作,继续遍历pushed数组中的其他元素即可。

如上就是这道题的解题思路了,下面我们还是举例来加深一下对这道题的理解。我们输入pushed = [1,2,3,4,5], popped = [4,5,3,2,1],如下就是具体的计算流程。请见下图所示:

图解LeetCode——剑指 Offer 31. 栈的压入、弹出序列_后端

图解LeetCode——剑指 Offer 31. 栈的压入、弹出序列_算法_02

四、代码实现

class Solution {
    public boolean validateStackSequences(int[] pushed, int[] popped) {
        Deque<Integer> deque = new ArrayDeque();
        int j = 0;
        for (int i = 0; i < pushed.length; i++) {
            deque.addLast(pushed[i]);
            while(!deque.isEmpty() && deque.peekLast() == popped[j]) {
                j++;
                deque.removeLast();
            }        
        }
        return deque.isEmpty();
    }
}

图解LeetCode——剑指 Offer 31. 栈的压入、弹出序列_算法_03

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」