02-线性结构4 Pop Sequence

129 阅读3分钟

Problem Description

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

Solution

思路启发自视频:PTA 出栈序列的合法性 (栈和队列的应用)

关键在于找到判断出栈顺序合法性的方法,这个方法具有普适性。

  • 题意是说给定了一个序列,按照固定的相对顺序随意入栈,判断输入所给的出栈序列是否合法

  • 我们需要构造一个固定的入栈相对顺序 order ,需要一个输入所给的待检验的出栈顺序 queue ,需要一个用来模拟的堆栈 stack

    • 在这个题目中, stack 的容量、queue 的长度都已知。三个都可以用数组来存,但此题固定的相对顺序为自然数序列,我的 order 就没有用数组存而是直接用 int 递增的方式表示
  • 算法思路(模拟):

    • 从固定顺序逐个入栈 stack ,每入栈一个元素就将 stack 栈顶元素 top 与 queue 队首元素 front 进行比较,如果相等,模拟成功,栈顶元素出栈,队首元素出队,循环比对直到栈顶元素与队首元素不再相等
    • 栈顶元素与队首元素不相等后,再次从固定顺序中入栈一个元素,继续进行以上比对方法
    • 循环退出条件有:
      • 整个序列模拟成功,front 最终值等于 n ,输出 YES
      • 所有元素都入栈后遇到无法比对成功的一组栈顶元素和队首元素,但已经没有元素可入栈,order > n ,循环退出,输出 NO
      • 遇不到一组能够比对成功的栈顶元素和队首元素,一直入栈直到爆栈循环退出,输出 NO
  • 归根结底就是模拟成功输出 YES ,模拟失败输出 NO

#include <stdio.h>
#include <stdlib.h>
  
int main()
{
    int i, m, n, k, order, top, front;
    int stack[1001], queue[1001];
  
    scanf("%d %d %d", &m, &n, &k);
    while (k--) {
        for (i = 0; i < n; i++) scanf("%d", &queue[i]);
  
        top = 0;
        front = 0;
        order = 1;
        while (order <= n && top < m) {
            stack[top] = order;
            while (top >= 0 && front < n && queue[front] == stack[top]) {
                top--;
                front++;
            }
            top++;
            order++;
        }
  
        if (front == n) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

以上是不用规范的数据结构与操作集实现的简易方法,毕竟数组操作比链表操作要简单。

也可以改成用规范的数据结构如 C++ 模板来实现算法,具有通用性。