Main22 栈的压入、弹出序列

剑指Offer_22 栈的压入、弹出序列


2018/6/8 星期五

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

一开始接触到这题,以为,压栈和出栈只存在一个情况。但是这样理解题目存在偏差,因为题目的意思明显是,压栈和入栈是可以交替进行的,比如,当我们压入1,2,3,4的时候,我们可以弹出4,再继续压入5,这样压入的顺序依旧是1,2,3,4,5。但是出栈的顺序就成为了4,5,3,2,1。具体的过程可以参考下表:

步骤 操作 弹出数字 步骤 操作 弹出数字
1 压入 1 6 压入 1,2,3,5
2 压入 1,2 7 弹出 1,2,3 5
3 压入 1,2,3 8 弹出 1,2 3
4 压入 1,2,3,4 9 弹出 1 2
5 弹出 1,2,3 4 10 弹出 1

理解题目的意思之后,我们开始分析。解决这个问题的想法是建立一个辅助栈,把输入的第一个序列中的数子依次压入该辅助栈中,并按照第二个序列的顺序依次从该栈中弹出该数字。判断一个数字是否弹出的标准是:

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

写下如下代码:

boolean isRight(int[] line1, int[] line2) {
    if (line1 == null || line2 == null) {
        return false;
    }
    int index = 0;
    Stack<Integer> stack = new Stack<>();
    for (int i = 0; i < line2.length && index < line1.length; ) {
        // ①
        if (!stack.isEmpty() && stack.peek() == line2[i]) {
            stack.pop();
            i++;
        } else {
            // ②
            stack.push(line1[index++]);
        }
    }
    // ③
    if (index == line1.length && stack.isEmpty()) {
        return true;
    }
    return false;
}

如果为了使代码更加高效,可以考虑省略其中的stack栈。

测试用例

  1. 功能测试:输入的数字中含有多个数字,或者只有1个数字,第二个序列是或者不是第一个压入序列对应的栈的弹出序列
  2. 特殊输入测试:两个空引用。

猜你喜欢

转载自blog.csdn.net/u013019701/article/details/80629180