题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
- 如果下一个弹出的数字刚好是栈顶数字,那么直接弹出。
- 如果下一个弹出的数字不在栈顶,我们把压栈序列中还没有入栈的数字压入辅助栈,直到把下一个需要弹出的数字压入栈顶为止。
- 如果所有的数字都压入栈了仍然没有找到下一个弹出的数字,那么该序列不可能是一个弹出序列。
代码1:
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
int len=pushA.length;
boolean result=false;
Stack<Integer> tempStack=new Stack<>();
int push_start=0;//记录push的第一个元素位置
int pop_start=0;//记录pop第一个元素的位置
int nextPush=0;//记录临时栈中下一个要压入的元素
int nextPop=0;//记录临时栈中下一个要弹出的元素
while(nextPop-pop_start<len){
while(tempStack.size()==0||tempStack.peek()!=popA[nextPop]){
//如果元素按压入序列全部压入临时栈,但是仍然没有找到和pop序列相等的元素
if(nextPush-push_start==len){
break;
}
tempStack.push(pushA[nextPush]);
nextPush++;
}
//元素全部压入栈中,仍然没有和弹出序列中pop出的元素相等的元素
if(tempStack.peek()!=popA[nextPop]){
break;
}
tempStack.pop();
nextPop++;
}
if(tempStack.size()==0&&nextPop-pop_start==len){
result=true;
}
return result;
}
}
推荐解法:
最简单的方法是建立一个临时栈,用来及记录压入顺序和弹出顺序的作用过程。遍历压入顺序,先将元素压入临时栈,再判断它是不是弹出顺序pop的元素,如果是,则把它从临时栈中弹出,如果不是,则继续压入。
遍历到最后,如果临时栈是空的,则说明弹出顺序是压入顺序的弹出序列。
否则,不是。
代码2:
/*借用一个辅助栈,遍历压栈的顺序
* 遍历压栈顺序,先将第一个元素放入辅助栈中,然后判断栈顶元素是不是出栈顺序的第一个元素,
* 如果不是,则继续压栈,知道栈顶元素和出栈顺序的第一个元素相等,
此时,出栈第一个元素,然后
* 将出栈顺序向后移动一位,接着判断。
* 这样循环,当压栈顺序遍历完成,如果辅助栈还不为空,则说明弹出序列不是该栈的弹出序列*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length==0||popA.length==0){
return false;
}
Stack<Integer> s=new Stack<Integer>();
int j=0;
for(int i=0;i<pushA.length;i++){
s.push(pushA[i]);
//如果临时栈不为空,且栈顶元素等于弹出顺序中的元素
while(!s.isEmpty()&&s.peek()==popA[j]){
s.pop();
j++;
}
}
return s.isEmpty();
}
}
因为本题在牛客上默认 引入的是ArrayList,而不是Stack,不知是否题意真正希望的是我们不借用栈而是借用ArrayList去实现这个功能,这个用ArrayList实现的方法是copy的别人的代码,https://www.nowcoder.com/profile/2670858/codeBookDetail?submissionId=25237020可以参考一下:
代码3:
import java.util.ArrayList;
public class Solution {
public boolean IsPopOrder(int [] pushA,int [] popA) {
if(pushA.length==0 || popA.length==0)
return false;
ArrayList<Integer> push = new ArrayList<Integer>();
ArrayList<Integer> pop = new ArrayList<Integer>();
//将数组复制到arraylist中
for(int x:pushA)
push.add(x);
for(int y:popA)
pop.add(y);
int currTop=0; //当前栈顶元素
int currPop=0;//当前要pop的值
for(int i=0;i<pop.size();i++){//外循环控制当前要pop的元素
for(int j=currTop;j<push.size();j++){
if(push.get(j)==pop.get(i)){
push.remove(j); //如果找到当前要删除的元素,那么将其删除
if(j>0){ //更新弹出栈顶元素后,新的栈顶index要前移一位
currTop = j-1;
}else{
currTop = 0;
}
currPop++; //已经弹出的元素个数
break; //如果已经在栈顶找到要删除的元素了,那么跳出内循环,开始寻找下一个要弹出的元素
}
if(j==push.size()-1){
return false; //如果所有元素都入栈了,还没有找到要弹出的元素,那么return false
}
}
}
//最后,根据currPop是否循环到了最后一个元素,来确定是否是弹出序列
if(currPop==pop.size()){
return true;
}else{
return false;
}
}
}