题目:
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
解法一:栈
用栈来存储压入的数字,然后出栈,判断出栈顺序是否与弹出序列一致。在入栈的过程中,如果栈顶元素与弹出序列当前下标的数字相同,则弹出栈顶元素,同时弹出序列下标后移。
入栈结束后,开始出栈,判断栈顶元素与弹出序列当前下标的数字是否相同,若不同,返回false,若相同,则弹出栈顶元素,同时弹出序列下标后移。
public boolean IsPopOrder(int [] pushA,int [] popA) {
Stack<Integer> stack = new Stack<>();
int j=0;
for(int i=0;i<pushA.length;i++){
stack.add(pushA[i]);
while(!stack.isEmpty()&&stack.peek()==popA[j]){
stack.pop();
j++;
}
}
for(int i=j;i<popA.length;i++){
if(!stack.isEmpty()&&stack.peek()==popA[i]){
stack.pop();
i++;
}else{
return false;
}
}
return true;
}
复杂度分析:
时间复杂度:O(N),最差遍历入栈数组一次,遍历栈一次,遍历弹出序列一次
空间复杂度:O(N),存储入栈数组
解法二:原地栈
把原数据数组当做栈,遍历数组进行入栈操作。当栈顶元素与弹出序列当前下标的值相同时,弹出栈顶元素n–,弹出序列下标后移j++。如
果不相同,继续遍历数组,进行入栈n++。相当于借助中间变量n把栈与数组连接起来,n充当数组的下标,也充当栈的深度。
public boolean IsPopOrder(int [] pushA, int [] popA) {
int j = 0;
int n = 0;
for (int num : pushA) {
pushA[n] = num;
while (n >= 0 && pushA[n] == popA[j]) {
n--;
j++;
}
n++;
}
return n == 0;
}
此方法虽然也能满足题意,但就是为了解题而解题,因为你改变了pushA数组,我仅仅是要判断一下是否满足要求,好家伙,你直接把原
数据给改了,不符合日常编码习惯,不推荐使用。
复杂度分析:
时间复杂度:O(N),最差遍历入栈数组一次,遍历弹出序列一次
空间复杂度:O(1),不涉及额外存储空间
总结:
涉及数据结构:栈
涉及算法:栈