题目描述
求解规定序列能否由入栈出栈操作得到
输入:
有若干组数据输入
每组数据中,第一行为两个个整数 n 和 m。n 表示总过程中需要依次从 1~n 入栈,m 表示这组数据有 m 个出栈序列需要判断,当 n=0 且 m=0 时停止。
接下来有行,每行表示一个出栈序列
输出:
对每一个出栈序列,如果能正常出栈,输出Yes,否则输出 No。
sample:
input:
5 2
1 2 3 4 5
5 4 1 2 3
6 1
6 5 4 3 2 1
0 0
output:
Yes
No
Yes
解题思路
本题就是怎么理解这个出栈序列的问题,也就是说什么样的出栈序列是合法的,又怎么判断?模拟?比较?或者其他算法(还不知道的)?
可以有一个思路,后面在判断树的生成时也可以用,也就是简单模拟。但是怎么操作呢,大概是检验的思想——该序列在进入的过程中我就用栈来模拟这个过程,怎样才能生成这样的序列?什么时候就明显不能生成这种序列了?
由于本题只能从小到大进栈,输入出栈序列,每输入一个数:只要当前栈顶不是这个数,就一直入栈,然后出栈顶;考查下一个数。
(1)可能是更大的。重复入栈;
(2)与当前栈顶一致。弹出栈顶,说明也就是按这个顺序出栈;
(3)小于当前栈顶。在弹出栈顶之前不可能弹出这个更小的数,所以不可能,可以否决了。
贴源代码
思路清晰之后其实很简单了,但是可能还有一些实现的小问题、细节,需要打磨一下。
比如每个用例结束的一个空行,有点烦,因为第一个和最后一个都没有空格,复制粘贴一遍还不如直接用times来记录次数,后面的每个打个空行。
还需要注意怎么记录之前已经进栈的最大数字,怎么push,怎么pop;当然,只要思路清晰别把自己绕进去了就很简单啦。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stack>
using namespace std;
int main()
{
int times = 0;
while (true) {
times++;
int n, m;
cin >> n >> m;
if (n == 0 && m == 0)
return 0;
else {
if (times != 1) cout << endl;
stack<int> s;
while (m--) {
if (!s.empty()) s.pop();
int tmp, maxhasinstack = 0;
bool yesorno = true;
for (int i = 0; i < n; i++)
{
cin >> tmp;
if (maxhasinstack < tmp)
{
int it = maxhasinstack + 1;
while (it < tmp) {
s.push(it);
it++;
}
maxhasinstack = tmp;
}
else {
if (tmp != s.top()) {
yesorno = false;
}
else
{
if (!s.empty())
s.pop();
}
}
}
if (yesorno)
cout << "Yes\n";
else
cout << "No\n";
}
}
}
}
——2022.10.13