Pop Sequence
题目要求:
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.
输入格式:
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.
输出格式:
For each pop sequence, print in one line “YES” if it is indeed a possible pop sequence of the stack, or “NO” if not.
输入样例:
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
输出样例:
YES
NO
NO
YES
NO
解题思路:
- 用数1-N模拟出栈序列,逐个序列进行判断。
- 具体判别方式:将1-N按次序比较后进行入栈出栈操作(与给定序列比较),核心在于比较栈顶元素与序列元素。
- 举例说明:比如说 5 6 4 3 7 2 1这个序列,首先我们自然由第一个出栈元素为5,推测出5出栈前栈里面应该为5 4 3 2 1(5为栈顶元素)。然后5出栈,这时根据第二个元素为6知道,栈应该是继续讲6入栈的,此时栈顶元素等于6,将6出栈。依次类推,只要比较栈顶元素和将要出栈的元素的大小,就可以知道该进栈还是出栈。当然,若是出现栈顶元素大于将要出栈的元素,或者虽然栈顶元素小于将要出栈的栈顶元素但此时栈已满都说明这个将要出栈的元素是不可能出现的。因此可以判断该出栈序列不合法。以上就是根据出栈序列,推测出栈和入栈操作的过程,关键是比较栈顶元素与“将要出栈元素”的大小(将要出栈的元素实际上就是给定序列元素,将给定序列元素视为将要出栈的元素)。
注意:
由于栈的大小和序列长度并不事先确定,需要用户输入,所以进行动态申请空间的方式 。
完整程序:
/*
【解题思路】
1.用数1-N模拟出栈序列,逐个序列进行判断。
2.具体判别方式:将1-N按次序比较后进行入栈出栈操作(与给定序列比较),核心在于比较栈顶元素与序列元素。
*/
//【注意】由于栈的大小和序列长度并不事先确定,需要用户输入,所以进行动态申请空间的方式
#include <stdio.h>
#include <stdlib.h>
typedef struct SNode {
int *Data;
int Top;
int MaxSize;
}*Stack;
/*全局变量,方便各函数引用*/
int M,N,K; // M:栈的最大容量,N:序列长度,K:待验证的序列个数
Stack CreateStack(int MaxSize); // 创建栈
int IsFull(Stack S); // 判断栈满
int IsEmpty(Stack S); // 判断栈空
void Push(Stack S,int ele); // 入栈
void Pop(Stack S); // 出栈
/*创建栈*/
Stack CreateStack(int MaxSize)
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S -> Top = -1;
S -> Data = (int *)malloc(MaxSize * sizeof(int));
S -> MaxSize = MaxSize;
return S;
}
/*判断栈满*/
int IsFull(Stack S)
{
if(S -> Top == S -> MaxSize - 1) // 栈满
return 1;
else // 栈未满
return 0;
}
/*判断栈空*/
int IsEmpty(Stack S)
{
if(S -> Top == -1) // 栈空
return 1;
else // 栈非空
return 0;
}
/*入栈*/
void Push(Stack S,int ele)
{
if(!IsFull(S))
S -> Data[++(S -> Top)] = ele;
else
return;
}
/*出栈*/
void Pop(Stack S)
{
if(!IsEmpty(S))
S -> Top --;
else
return;
}
/*检查序列*/
// 检查给定序列是否为该栈的可出栈序列
int SeqCheck(int *seq,Stack S)
{
int idx = 0; // seq数组的下标,指向下一个将要出栈的数
int num = 1; // 按顺序进栈的元素,进栈后自动加1
S -> Top = -1; // 先让栈置空
while(idx != N) { // 循环执行的条件是:没有将N个数全部出栈
while(IsEmpty(S) || !IsFull(S) && S -> Data[S -> Top] < seq[idx])
Push(S,num ++); // 栈为空栈且没有将N个数全部出栈(该情况下说明还未有元素入栈) 或 栈未满且栈顶元素小于将要比较的出栈元素(序列的对应元素)
if(S -> Data[S -> Top] == seq[idx]) { // 栈顶元素等于将要比较的出栈元素(序列对应元素)
Pop(S);
idx ++;
}
if(IsFull(S) && S -> Data[S -> Top] < seq[idx] || S -> Data[S -> Top] > seq[idx])
return 0; // 栈顶元素小于将要比较的出栈元素(序列对应元素),则说明该序列不是该栈的可出栈序列
}
return 1;
}
int main()
{
Stack S;
scanf("%d %d %d",&M,&N,&K);
int *seq = (int *)malloc(N * sizeof(int)); // 存放待验证序列的数组
S = CreateStack(M);
for(int i = 0;i < K;i ++) {
for(int j = 0;j < N;j ++)
scanf("%d",&seq[j]);
if(SeqCheck(seq,S))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}