栈的压入、弹出序列

问题描述

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。

例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。

示例 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:

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

问题分析

这题主要考察对栈的理解,栈是一种先进后出的数据结构,如果栈顶元素不出栈,那么栈顶元素下面的元素都是不能出栈的。

一种解决方式就是把pushed数组的元素逐个压栈,当栈顶元素等于popped数组中第一个元素的时候,就让栈顶元素出栈,这个时候再用popped数组的第2个元素和栈顶元素比较,如果相同继续出栈……,最后判断栈是否为空即可,来看下代码

import java.util.*;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        Stack pushStack = new Stack();
        int popIndex = 0;
        for(int i = 0;i < pushA.length;i++){
            pushStack.push(pushA[i]);
            while(!pushStack.isEmpty() && popA[popIndex]==pushStack.peek()){
                pushStack.pop();
                popIndex++;
            }
        }
        return pushStack.isEmpty(); 
    }
}

另一种解决方式就是排除不可能的popped序列组合,解决思路如下:
在pushed数组中,如果排在当前入栈元素后面的多个元素也入栈了,则后面的多个入栈元素必定先出栈,否则不符合出栈的特性。

因此,我们可以一开始就记录下入栈元素的初始下标,使用map结构,key:入栈元素值,value:入栈元素的初始下标。

排除不可能的情况:
遍历出栈数组中的每一个元素,如果当前出栈元素的下标(currIndex)与前一个出栈元素的下标(beforeIndex)差的绝对值大于1或与后一个出栈元素的下标(afterIndex)差的绝对值大于1,满足beforeIndex > currentIndex ,则currentIndex > afterIndex 才符合出栈特性。所以我们要排除beforeIndex > currentIndex && currentIndex < afterIndex的情况。

注意:beforeIndex < currentIndex 则 currentIndex 与 afterIndex的大小无特别要求。
如果pushed数组长度<=1需要单独考虑。长度为1没法前后比较,只需要判断pushed和popped数组元素值是否相等即可。

代码实现如下:

import java.util.*;

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        // 如果pushA长度小于等于1需要单独判断
        if(pushA.length == 0 && popA.length == 0){
            return true;
        }
        if(pushA.length == 1 && popA.length == 1){
            return  pushA[0] == popA[0];
        }
        // pushA的value和index存入map
        Map pushMap = new HashMap<>();
        boolean result = true;
        for(int i = 0;i < pushA.length;i++){
            pushMap.put(pushA[i],i);
        }
        // 不符合情况排除
        for(int i = 1;i < popA.length-1;i++){
            int currIndex = pushMap.get(popA[i]);
            int beforeIndex = pushMap.get(popA[i-1]);
            int afterIndex = pushMap.get(popA[i+1]);
            if(Math.abs(currIndex - beforeIndex) > 1 || Math.abs(currIndex - afterIndex) > 1){
                if(currIndex < beforeIndex && currIndex < afterIndex){
                    result = false;
                    break;
                }
            }
        }
        return result;
    }
}

你可能感兴趣的:(栈的压入、弹出序列)