栈的push、p op序列
题目:输入两个整数 序列。其中一个序列表示栈的push顺序 ,
判断另一个序列有没有可能是对应的pop顺序。
为了简单起见,我们假设 push序列的任意两个整数都是不相等的。
比如输入的push序列是1、2、3、4、5,那 么 4、5、3、2、1就有可能是一个pop系列。
因为可以有如下的push和pop序列:
push 1,push 2,push 3,push 4,pop, push 5,pop,p op,pop,pop,
这样得到的pop序列就是4、5、3、2、1。
但序列4、3、5、1、2就不可能是push序列1、2、3、4、5的pop序列。
----------------------------------------------------------------------------
方法一:用栈模拟过程
这道题其实第一个方法大家可以很快想到,我们不妨模拟这个栈,自己写一个栈的push pop然后根据pop序列来模拟pop过程
例如:
Push:1 2 3 4 5
Pop: 4 5 3 2 1
我们先得到pop的第一个元素是4,然后我们开始push,直到Push(4)的时候,我们知道,这里要把4pop出来,
然后移动pop序列到下一个元素5,我们先检查此时的栈顶元素3是不是Pop元素,当然不是,所以继续push,这时候push进来的正是5,然后移动Pop到下一个元素,是3,此时栈顶元素就是3,然后pop(3)接下来过程就很好理解了,所以 模拟一个栈的方法是可以的。
————————————
这里插入个注意事项:
1、什么时候停止?或者说什么时候能够判断这个pop就是push对应的呢?一定要把push都push完才算还是Pop遍历完才算?
当然是pop遍历结束就可以了,例如
push: 1 2 3 4
pop: 4 3
你说这个是不是对应的push pop?当然是,因为Pop序列是可以从push中得到的!
2、如果发现某个元素根本就不再push序列里,就可以停止了!
——————————
方法2:不用栈,采用逻辑模拟
这里可以采用数组来模拟栈,我下面给的程序就是这个过程,push_num表示栈顶指针
同样,先得到pop第一个元素,然后根据改元素值在push中找到,然后将该元素push,我这里假设为-1,然后找下一个pop元素,
因为此时被Push的元素只有两种可能,一个是刚被push元素的前一个元素,要们就是后面push的某个元素,所以遵循这个过程找下一个
比较上面两个方法,第一种方法时间复杂度可以看成是O(N)是用空间换来的O(2N)
第二种方法则在时间复杂度上达到O(N^2)所以。。。
//============================================================================
// Name : PushPop.cpp
// Author : YLF
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include <iostream>
#include <string.h>
using namespace std;
#define MAX 100
int Input(int arr[]);
void Output(int arr[], int num);
bool PushPop(int* push, int push_num, int* pop, int pop_num);
int main() {
int push[MAX];
int pop[MAX];
int push_num=-1, pop_num=-1;
push_num = Input(push);
pop_num = Input(pop);
if(PushPop(push, push_num, pop, pop_num))
cout<<"yes";
else
cout<<"no";
cout<<endl;
Output(push, push_num);
Output(pop, pop_num);
return 0;
}
bool PushPop(int* push, int push_num, int* pop, int pop_num){
int i =0,j = 0;
while(j<pop_num){
//向前找一个,就是找当前栈顶元素是不是Pop对应的
if(i>0){
while(i>0 && push[i]==-1)
i--;
if(i>=0 && push[i]!=-1){
if(push[i]==pop[j]){
//把前一个再pop出来了
push[i]=-1;
j++;
continue;
}
}
}
//向后找
while(i<push_num && push[i]!=pop[j])
i++;
if(i<push_num && push[i]==pop[j]){
push[i] = -1;
}else{
cout<<i<<" "<<j<<endl;
return false;
}
j++;
}
return true;
}
int Input(int arr[]){
int num = -1;
int input;
while(true){
num++;
cin>>input;
if(input!=-1)
arr[num] = input;
else
break;
}
return num;
}
void Output(int arr[], int num){
int i = 0 ;
for(;i<num;i++)
cout<<arr[i]<<" ";
cout<<endl;
}
测试:
1 2 3 4 5 -1
3 7 -1
5 1
no
1 2 -1 4 5
3 7
1 2 3 4 5 -1
3 2 1 -1
yes
-1 -1 -1 4 5
3 2 1
1 2 3 4 5 -1
4 5 3 2 1 -1
yes
-1 -1 -1 -1 -1
4 5 3 2 1