题目名称 : 队列重排(数据结构)
时间限制 : 1000 ms
空间限制 : 32 MB
问题
给定一个队列,如,1,2,3, 其中1是队头,问能否通过一个栈得到新的队列,如得到2,3,1 是可以的,得到3,2,1也是可以的,但是得到3,1,2是不可能的。
输入
第一行是一个整数n,表示队列的元素(整数)个数, 下一行是由n个不同元素构成的初始队列(第一个是队头),再下一行是一个整数m, 接下来是需要检查的m行整数序列,每行由初始队列的n个元素构成(第一个元素是队头),表示可能的重新排列。
输出
对初始队列元素的每个排列,如果可以通过一个栈得到,则输出"YES",否则输出"NO",每个输出占一行。
Sample Input
3
1 2 3
6
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Sample Output
YES
YES
YES
YES
NO
YES
这似乎也是个经典的问题,叫合法在出栈序列:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
int main()
{
int n;
cin>>n;
vector<int> v; //队列
for(int i=0;i<n;i++)
{
int elem;
cin>>elem;
v.push_back(elem);
}
int m;
cin>>m;
vector<vector<int> > seqs; //一个序列组,装着m个序列
while(m--)
{
vector<int> seq;//一个要判断合法性的序列
for(int i=0;i<n;i++){
int elem;
cin>>elem;
seq.push_back(elem);
}
seqs.push_back(seq);//将这个序列push进序列组中存储起来
}
for(int i=0;i<seqs.size();i++)//开始检查序列组中每一个出栈序列的合法性
{
stack<int> stk;
int cnt=0;
//下面开始模拟队列v的入栈出栈
for(int j=0;j<n;j++)//逐个比对队列v中的数字
{
if(v[j]==seqs[i][cnt])//当前队列头=出栈序列头,说明这个数字可以直接出队列、进栈、出栈一气呵成
{
cnt++;//比对出栈序列头的下一个数字
}
else if(!stk.empty()&&stk.top()==seqs[i][cnt])//出栈序列头=栈顶数字,说明可以从栈中弹出一个数字,而队列头不需要出队
{
cnt++;
stk.pop();
j--; //队列头不出队,因此下次仍需比对这个队列头
}
else{//其他情况,则将队列头出队,并压进栈中
stk.push(v[j]);
}
}
while(!stk.empty()){//队列元素已全部出队,此时将栈内元素出栈,看是否于剩余部分的出栈序列一致
if(stk.top()!=seqs[i][cnt]) break;
else{
stk.pop();
cnt++;
}
}
if(stk.empty()) cout<<"YES\n";
else cout<<"NO\n";
}
}