题目描述
给定一个最多可以保留 M 个数字的堆栈。按 1、2、3、…、N 的顺序推送 N 个数字并随机弹出。您应该判断给定的数字序列是否是堆栈的可能弹出序列。例如,如果 M 是 5,N 是 7,我们可以从堆栈中得到 1、2、3、4、5、6、7,但不能得到 3、2、1、7、5、6、4。
输入规格:
每个输入文件都包含一个测试用例。对于每种情况,第一行包含 3 个数字(均不超过 1000):M(堆栈的最大容量)、N(推送序列的长度)和 K(要检查的弹出序列数)。然后是 K 行,每行都包含 N 个数字的弹出序列。一行中的所有数字都用空格分隔。
输出规格:
对于每个弹出序列,如果它确实是堆栈的可能弹出序列,则在一行中打印“YES”,如果不是,则打印“NO”。
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
代码展示
本题的思路是,将元素按1,2,3…N的顺序入栈,并且按照题目所给的序列来出栈(采用的方法是:每次入栈一个元素后,检查栈顶元素是否是题目所给序列中的当前出栈元素,若是则出栈)
如果最后栈为空,那么说明题目所给序列是合法的,否则不合法
#include <stdio.h>
#define MAXSIZE 1000
typedef struct stack
{
int a[MAXSIZE];
int top;
} stack;
void clearStack(stack* s)
{
s->top = -1;
}
void push(stack* s, int e)
{
s->a[++s->top] = e;
}
int pop(stack* s)
{
int e = s->a[s->top];
s->top--;
return e;
}
int isEmpty(stack* s)
{
if (s->top == -1) return 1;
else return 0;
}
int main()
{
int M, N, K; //M:堆栈的最大容量 N: 推送序列的长度 K:共有K行数据
scanf("%d %d %d", &M, &N, &K);
int res[MAXSIZE] = { -1 };
stack s;
s.top = -1;
for(int count = 0; count < K; count++)
{
clearStack(&s);
int cur = 0; //出栈序列当前元素位置
int out[MAXSIZE] = { 0 }; //存储出栈序列
//将出栈序列存入out数组
for (int i = 0; i < N; i++)
{
scanf("%d", &out[i]);
}
//按照入栈序列的顺序,依次将元素压入辅助栈。
for (int i = 1; i <= N; i++)
{
if (s.top < M - 1)
{
push(&s, i);
}
//压入后,检查栈顶元素是否与出栈序列当前指针指向的元素相同
//如果相同,则将该元素出栈,且指针向后移动一位。
while (!isEmpty(&s) && s.a[s.top] == out[cur])
{
pop(&s);
cur++;
}
}
//先将结果统一保存到数组中,最后再集中打印
if (isEmpty(&s))
{
res[count] = 1;
}
else
{
res[count] = 0;
}
}
for (int i = 0; i < K; i++)
{
if (res[i] == 1)
{
printf("YES\n");
}
if (res[i] == 0)
{
printf("NO\n");
}
}
return 0;
}