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,输入序列的元素数量N,输入序列的数量K。然后每一行都为一个出栈序列,如果输入序列有N个值,那么入栈序列为1,2,3,…,N。
规则是:出栈序列中的每个数后面的比它小的数,是按递减排列的。
简化规则描述:
1、假设入栈顺序为1234。
1)若出栈序列为4123,显然不满足上述要求,因为对于4,它后面比它小的数字序列为123,而123是一个递加系列即不是递减排列,所以不是合法出栈序列。
2)若出栈系列为3142,也不合法,因为3后面比它小的1和2不是递减排列的。
3)若出栈系列为1234,则合法,因为对于每一个数字它后面没有比它小的数字。
2、假设入栈顺序为123456789abcdef。
1)若出栈系列为67d51f94e2ba83c,因为对于d,它后面比它小的19或123或ac等等都不是递减的,所以不合法。
2)若出栈系列为379a8b65c4ed21f,可以证明是合法的出栈顺序。因为对于每一个数字它后面没有比它小的数字而且是按递减排列的。
3、证明:
假设入栈顺序为1234…n,可知在栈中的元素从栈顶到栈底一定是按严格递减排列的,而且每个数i进栈之前,比i小的数一定已经进栈了。
所以比i小的数要不然已经出栈,要不然在栈中,如果还在栈中则一定在i的下面,按严格递减排列,如此可见如果比i小的数还在栈中则一定在i之后输出,所以输出序列中在i后面的比i小的数一定按严格递减排列.否则出栈系列不合法。
思路:用一个辅助栈存储入栈序列,按出栈序列出栈,如果最后栈为空,则序列合法。
- 如果辅助栈不满,且入栈序列不空,入栈序列的下一个元素入栈
- 如果辅助栈的栈顶元素不等于出栈序列的首元素,一直入栈直到入栈序列为空
- 如果栈顶元素等于出栈序列的首元素,辅助栈顶元素出栈,指针移向出战序列的下一个元素
- 最后检查辅助栈是否为空,如果为空,说明出栈序列合法
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 1000
typedef struct SNode *Stack;
struct SNode{
int Data[MaxSize];
int Top;
}snode;
int Push(Stack S, int X){
if (S->Top == MaxSize-1) {
//printf("堆栈满\n");
return 0;
}
S->Top++;
S->Data[S->Top] = X;
return 1;
}
int Pop(Stack S){
if (S->Top == -1) {
//printf("堆栈空\n");
return 0;
}
else
return (S->Data[(S->Top)--]);
}
int main(int argc, const char * argv[]) {
int M, N, K;//栈的最大容量,单个序列元素个数,输入序列个数
scanf("%d %d %d", &M, &N, &K);
int i, j;
Stack S;//辅助栈
int v[N];
for (i = 0; i<K; i++) {
int current = 0;
S = &snode;
S->Top = -1;
for (j = 0; j<N; j++) {
scanf("%d", &v[j]);
}
for (j = 0; j<N; j++) {
Push(S, j+1);
//如果栈满还在入栈,说明此序列不合法
if (S->Top+1 > M) {
break;
}
//如果栈不为空并且栈顶元素和出栈序列相等,出栈
while (S->Top!=-1 && S->Data[S->Top] == v[current]) {
Pop(S);
current++;
}
}
//入栈与出栈数相等,说明此时栈为空,所有元素都访问过了,此序列合法
if (p->Top == -1) {
printf("YES\n");
}
else
printf("NO\n");
}
return 0;
}