剑指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 |
理解题目的意思之后,我们开始分析。解决这个问题的想法是建立一个辅助栈,把输入的第一个序列中的数子依次压入该辅助栈中,并按照第二个序列的顺序依次从该栈中弹出该数字。判断一个数字是否弹出的标准是:
- 如果下一个弹出的元素刚好是栈顶元素,那么直接弹出;
- 如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。
- 如果所有的数字都压入栈了仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。
写下如下代码:
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个数字,第二个序列是或者不是第一个压入序列对应的栈的弹出序列
- 特殊输入测试:两个空引用。