【剑指Offer】21、栈的压入、弹出序列

  题目描述:

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

  解题思路:

  本题很直观的一个想法就是建立一个辅助栈,用该栈根据给出的序列来模拟压栈、弹栈动作,进而判断该序列是否可能正确。解决这样的问题一般不太好分析,可以通过几个具体的实例,使问题具体化,进而发现普遍规律。

  以以下两个例子为例,我们可以找到判断一个序列是不是栈的弹出序列的规律:根据弹出序列,我们依次进行判断,如果下一个要弹出的数字刚好是栈顶数字,那么直接弹出;如果下一个要弹出的数字不在栈顶,则把压栈序列中还没有入栈的数字压入栈中,直到将下一个要弹出的数字压入栈顶为止,如果所有的数字都压入栈中后仍然没有找到下一个要弹出的数字,那么该序列就不可能是一个弹出序列。

  举例:

  编程实现(Java):

public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
      /*思路:模拟压栈和出栈过程
      规律是:根据弹出序列,如果下一个弹出的元素正好是栈顶元素,则弹出;如果下一个弹出的数字不是栈顶元素,则将还未进栈的元素依次进栈,
      直到找到要弹出的那个数字;最终,如果所有数字都压入栈中还没有找到弹出元素,则说明不是一个弹出序列
      */
        if(pushA==null || popA==null)
            return false;
        Stack<Integer> stack=new Stack<>();  //辅助栈,用来模拟该过程
        int p=0; //进栈序列下标
        int len=pushA.length;
        for(int i=0;i<popA.length;i++){
            //当前需要弹出的是popA[i]
            if(!stack.empty()&& stack.peek()==popA[i]) //弹出的元素正好是栈顶元素
                stack.pop();
            else{ //下一个弹出的数字不是栈顶元素
                while(p<len && pushA[p]!=popA[i]){  //所有数字都压入栈中还没有找到弹出元素,则说明不是一个弹出序列
                    stack.push(pushA[p]);
                    p++;
                }
                p++;
            }
        }
        return stack.isEmpty();    
    }
}
posted @ 2019-04-29 12:41  gzshan  阅读(1110)  评论(0编辑  收藏  举报