题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
分析
判断一个序列是不是栈的弹出序列的规律:如果下一个弹出元素刚好是栈顶元素,则直接弹出。如果下一个弹出的元素不在栈顶,则把入栈序列中还没有入栈的元素入栈,直到把下一个需要弹出的元素入栈为止。如果所有的元素都入栈了仍然没有找到下一个弹出的元素,那么该序列不可能是一个弹出序列。
牛客AC代码:
package com.problem;
/**
* 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。
* 假设压入栈的所有数字均不相等。
* 例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,
* 但4,3,5,1,2就不可能是该压栈序列的弹出序列。
*/
import java.util.Stack;
public class IsPopOrderOfStack {
public static void main(String[] args) {
int[] pushArr = {1, 2, 3, 4 ,5};
int[] popArr = {4, 5 ,3 ,2 ,1};
int[] popArr2 = {4,3 ,5, 1,2};
System.out.println(isPopOrder(pushArr, popArr)); // true
System.out.println(isPopOrder(pushArr, popArr2)); // false
}
public static boolean isPopOrder(int[] pushArr,int[] popArr) {
if(pushArr == null ||
popArr == null ||
pushArr.length <= 0 || pushArr.length <=0 ||
pushArr.length != popArr.length)
return false;
boolean isPopOrder = false;
int length = pushArr.length;
Stack<Integer> stack = new Stack<Integer>();
int nextPushIndex = 0; // 下一个入栈索引
int nextPopIndex = 0; // 下一个弹出索引
while(nextPopIndex < length) {
// 如果数据栈为空,或者数据栈顶元素不等于需要弹出的元素,
// 则按照入栈顺序入栈,知道找到需要弹出的元素并且入栈为止
while(stack.empty() || stack.peek() != popArr[nextPopIndex]) {
if(nextPushIndex == length) // 所有元素已经入栈
break;
stack.push(pushArr[nextPushIndex]);
nextPushIndex++;
}
// 入栈完成后,栈顶元素仍然不是需要弹出的元素,则不可能是弹出序列
if(stack.peek() != popArr[nextPopIndex])
break;
// 否则,栈顶元素是需要弹出的元素,将其直接弹出,处理下一个弹出元素
stack.pop();
nextPopIndex++;
}
// 所有元素处理完成后,数据栈应当为空,并且索引值达到最大length
if(stack.empty() && nextPopIndex == length)
isPopOrder = true;
return isPopOrder;
}
}
参考
1. 何海涛,剑指offer名企面试官精讲典型编程题(纪念版),电子工业出版社