出栈序列的合法性
一、问题简述
-
给定一个入栈序列,给出一系列出栈顺序,判断出栈序列是否合法。
-
例如:入栈序列[1,2,3,4],
出栈序列[4,3,2,1]合法,
[3,4,2,1]合法,
[3,1,2,4]不合法。
二、算法设计
-
建立一个主栈s1和一个辅助栈s2,将给定的出栈序列反向push到主栈s1。
-
以从1-n的顺序向辅助栈s2逐一push元素:
-
检查s2的栈是否为空且s2栈顶元素与s1的栈顶元素是否相同。
-
若相同就分别pop出s1和s2的栈顶元素直到s2栈空或者s1与s2栈顶元素不同为止。
-
若最终s2栈空则该出栈序列合法。
-
-
以[3,4,2,1]为例
- 代码实现
bool function (vector<int> & seq){
stack<int> s1,s2;
for(int i=seq.size()-1;i>=0;i--){
s1.push(seq[i]);
}
for(int i=1;i<=seq.size();i++){
s2.push(i);
while(!s2.empty()&&s1.top()==s2.top()){
s1.pop();
s2.pop();
}
}
if(s2.empty()){
return true;
}else{
return false;
}
}
三、背景题目:堆栈的基本操作(北大poj平台)
-
总时间限制: 1000ms
-
内存限制: 65535kB
-
描述
依次读入序列元素1,2,…,n进栈,每进一个元素,机器可要求下一个元素进栈或弹栈,如此进行。给定一个输入序列,判断栈空时弹出的元素构成的序列是否可能等于给定的序列,如果是则输出栈的操作过程,否则输出“NO”。
-
输入
输入分两行 第一行为n的值(即序列元素个数) 第二行为给定的输入序列(序列元素均为整型)
-
输出
如果输入序列能够由题目规定的操作得到,则输出对栈的操作过程 否则直接输出“NO”
-
样例输入
7
4 5 3 6 2 7 1
- 样例输出
PUSH 1
PUSH 2
PUSH 3
PUSH 4
POP 4
PUSH 5
POP 5
POP 3
PUSH 6
POP 6
POP 2
PUSH 7
POP 7
POP 1
-
提示
给定序列中有可能有不在1…n之间的数字
四、代码实现
#include<iostream>
#include<stack>
#include<vector>
using namespace std;
bool function (vector<int> & seq){
stack<int> s1,s2;
for(int i=seq.size()-1;i>=0;i--){
s1.push(seq[i]);
}
for(int i=1;i<=seq.size();i++){
s2.push(i);
while(!s2.empty()&&s1.top()==s2.top()){
s1.pop();
s2.pop();
}
}
if(s2.empty()){
return true;
}else{
return false;
}
}
void fun(vector<int> & seq){
stack<int> s1,s2;
for(int i=seq.size()-1;i>=0;i--){
s1.push(seq[i]);
}
for(int i=1;i<=seq.size();i++){
s2.push(i);
cout<<"PUSH "<<i<<endl;
while(!s2.empty()&&s1.top()==s2.top()){
cout<<"POP "<<s2.top()<<endl;
s1.pop();
s2.pop();
}
}
}
int main(){
int n;
cin>>n;
vector<int> arr;
for(int i=0;i<n;i++){
int x;
cin>>x;
arr.push_back(x);
}
if(function(arr)){
fun(arr);
}else{
cout<<"NO";
}
return 0;
}