Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, …, N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.
Input Specification:
Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.
Output Specification:
For each pop sequence, print in one line “YES” if it is indeed a possible pop sequence of the stack, or “NO” if not.
Sample Input:
5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2
Sample Output:
YES
NO
NO
YES
NO
题目大意:给定一个大小为M的栈和一个原始序列1,2,3…N,将原始序列中的值push到栈中,push时必须按顺序push,从栈中弹出时可在任意时刻弹出。现在输入目标序列,问能不能按目标序列的顺序从栈中弹出。
解题思路:下面用一个例子来描述这道题的解题思路:
目标序列为:5 6 4 3 7 2 1
| 原始序列 | 栈 | 操作 |
|---|---|---|
| 7 6 5 4 3 2 1 | - | - |
| 7 6 | 5 4 3 2 1(栈底) | 按顺序压栈,直到5进栈(因为目标序列第一个值为5) |
| 7 6 | 4 3 2 1 | 弹出5 |
| 7 | 6 4 3 2 1 | 压栈,直到6进栈 |
| 7 | 2 1 | 弹出6,4,3 |
| - | 7 2 1 | 压栈,直到7进栈 |
| - | 7 2 1 | 弹出 7 2 1 |
弹出顺序:5 6 4 3 7 2 1 输出YES。
详细解释:目标序列的第一个数是5,要想从栈中弹出5,栈中必须要有5,所以现在按原始序列依次将值push到栈中,直到栈变成了 5 4 3 2 1(栈底),此时栈中有了想要的5且在栈顶,所以此时可pop,pop后栈变成了 4 3 2 1(栈底),目标序列变为了 6 4 3 7 2 1,继续上面的思路,这次想弹出6,则栈中先要有6,所以继续按原始顺序压栈,直到栈变为 6 4 3 2 1(栈底),现在有6了且在栈顶,可pop,现在栈变为了4 3 2 1(栈底),目标序列变为了 4 3 7 2 1,可以到可直接从栈中弹出4和3,然后栈变为了2 1(栈底),目标序列变为了7 2 1,缺7,然后push 7,然后栈变为了7 2 1,和目标序列相同了,所以直接按顺序pop就行。
上面展示的是输出为YES的示例,输出为NO的情况非常好判断,如果栈中存在目标序列的第一个数,但是那个数不在栈顶,此时就无法按目标序列pop。
在上面模拟的过程中,我们频繁使用的一个操作是检查栈中是否存在我们想要的数,但是由于栈自身的限制无法高效地实现这样地查询,所以我们使用一个set辅助查找,每次压栈都将值插入到set中,需要查询栈中是否存在某个值时直接在set中查询即可。
说起这道题的解题思路,还得追溯到中山大学计算机夏令营的模拟机试?,说起来我又忍不住想吐槽下他们的模拟机试和正式机试,说起来是模拟,但是风格完全不同,模拟机试时几乎全是算法题,没有关于面向对象编程的内容,正式机试时好几道题都是关于类的,什么多态啊,运算符重载啊,写得我很是心碎?。
代码:
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char const *argv[])
{
int M, N, K;
cin >> M >> N >> K;
while(K--){
vector<int> num(N); // 输入的目标序列
vector<int> origin(N); // 原始序列 1,2,3,4,5...N
for(int i = 0;i < N; i++){
cin >> num[i];
origin[i] = i+1;
}
stack<int> sk; // 尺寸最大为M的栈
set<int> st; // 栈中的数
int i = 0,j = 0, succ = 1;
while(1){
// 目标序列中的第一个数不在栈中则按原始序列的顺序一直往栈中push
while(i < N && j < N && st.count(num[j]) != 1 && sk.size() < M){
st.insert(origin[i]);
sk.push(origin[i]);
i++;
}
// 如果栈中的第一个值就是目标序列的第一个值,
if(sk.top() == num[j]){
sk.pop();
st.erase(num[j]); // 此行可省略
j++;
}
else{
succ = 0;
break;
}
// 整个序列都已输出
if(j == N)
break;
}
cout << ((succ == 1) ? "YES" : "NO" ) << endl;
}
return 0;
}
本文深入探讨了如何判断一个给定序列是否能通过特定大小的栈进行匹配的问题,提供了详细的解题思路和代码示例,重点讲解了如何利用辅助数据结构优化查询效率。
722

被折叠的 条评论
为什么被折叠?



