3:堆栈基本操作
总时间限制: 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之间的数字
参考了一下csdn上的代码并进行了一些优化
思路:
用一个栈x来实现输入序列的反向输出
用另一个栈y来模拟原序列的输入,并通过y.top()==x.top来判断是否需要pop
(一般情况,只需要不停比对top,最后两个都空了就行)
(特殊情况1,两个栈都pop空了,所以要加上!y.empty()的判断)
(特殊情况2,给定序列中有可能有不在1...n之间的数字,这个时候y可能是空的但是x不是,为避免调用y.top,所以在特1里用的是!y.empty)
当y全部输入,且执行完pop对比后,如果非空,代表不行,输出NO
由于NO的情况,不需要输出push和pop,则用一个函数judge判断,另一个函数f输出
写给我自己:
1.scanf,加&输入
printf,加&表示取地址,故不加&
2.利用好vector和stack,注意格式vector<int>
#include <bits/stdc++.h>
using namespace std;
int n;
vector<int> aa;
bool judge(vector<int> &a){
stack<int> x,y;
for(int i=a.size()-1;i>=0;--i)
x.push(a[i]);
for(int i=1;i<=n;++i){
y.push(i);
while(!y.empty()&&x.top()==y.top()){
x.pop();
y.pop();
}
}
if(!x.empty()){
printf("NO");
return 1;
}
else return 0;
}
void f(vector<int> &a){
stack<int> x,y;
for(int i=a.size()-1;i>=0;--i)
{
x.push(a[i]);
}
for(int i=1;i<=n;++i){
y.push(i);
printf("PUSH %d\n",i);
while(!y.empty()&&x.top()==y.top()){
printf("POP %d\n",x.top());
x.pop();
y.pop();
}
}
}
int main(){
int x,y;
scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%d",&y);
aa.push_back(y);
}
if(aa.size()!=n){
printf("NO");
return 0;
}
if(judge(aa)) return 0;
else f(aa);
}