题目
给定一个可以保持的堆栈M最多数字。推N数字按 1、2、3、...、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”。
示例输入:
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
题解:
#include <stdio.h>
#include <stdbool.h>
typedef struct {
int capacity;
int stack[1000];
int top;
} Stack;
void initStack(Stack *s, int capacity) {
s->capacity = capacity;
s->top = -1;
}
void push(Stack *s, int num) {
if (s->top < s->capacity - 1) {
s->stack[++(s->top)] = num;
}
}
int pop(Stack *s) {
if (s->top >= 0) {
return s->stack[(s->top)--];
}
return -1;
}
bool isPossiblePopSequence(int M, int N, int sequence[]) {
Stack s;
initStack(&s, M);
int currentPush = 1;
for (int i = 0; i < N; i++) {
while (currentPush <= sequence[i]) {
push(&s, currentPush++);
}
int popped = pop(&s);
if (popped != sequence[i]) {
return false;
}
}
return true;
}
int main() {
int M, N, K;
scanf("%d %d %d", &M, &N, &K);
for (int i = 0; i < K; i++) {
int sequence[1000];
for (int j = 0; j < N; j++) {
scanf("%d", &sequence[j]);
}
if (isPossiblePopSequence(M, N, sequence)) {
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}
当涉及堆栈和代码逻辑时,理解可能需要更详细的解释。我会逐步解释我提供的代码,帮助你更好地理解每一部分。
定义结构体
typedef struct {
int capacity;
int stack[1000];
int top;
} Stack;
这段代码定义了一个结构体 Stack
,它表示一个堆栈数据结构。这个结构体有三个成员变量:
int capacity
: 表示堆栈的容量,即能够容纳的最大元素数量。int stack[1000]
: 一个整型数组,用来存储堆栈的元素。int top
: 表示堆栈的顶部元素的索引。
initStack
函数初始化堆栈:
void initStack(Stack *s, int capacity) {
s->capacity = capacity;
s->top = -1;
}
这个函数接受一个指向 Stack结构体的指针 s,以及堆栈的容量 capacity。它将 capacity赋值给堆的capacity成员,并将 top初始化为 -1,表示堆栈为空。
push
函数将元素推入堆栈:
void push(Stack *s, int num) {
if (s->top < s->capacity - 1) {
s->stack[++(s->top)] = num;
}
}
这个函数接受一个指向 Stack
结构体的指针 s
,以及要推入堆栈的元素 num
。它首先检查堆栈是否还有空间(s->top < s->capacity - 1
),如果有空间,则将 num
推入堆栈中,并将 top
值递增。
pop
函数从堆栈中弹出元素:
int pop(Stack *s) {
if (s->top >= 0) {
return s->stack[(s->top)--];
}
return -1;
}
这个函数接受一个指向 Stack
结构体的指针 s
。它首先检查堆栈是否非空(s->top >= 0
),如果非空,则返回堆栈顶部元素的值,并将 top
值递减。
判断堆栈
最后,isPossiblePopSequence
函数用来判断给定的弹出序列是否可能是堆栈的弹出序列:
bool isPossiblePopSequence(int M, int N, int sequence[]) {
Stack s;
initStack(&s, M);
int currentPush = 1;
for (int i = 0; i < N; i++) {
while (currentPush <= sequence[i]) {
push(&s, currentPush++);
}
int popped = pop(&s);
if (popped != sequence[i]) {
return false;
}
}
return true;
}
这个函数接受堆栈的最大容量 M
,弹出序列的长度 N
,以及表示弹出序列的整型数组 sequence[]
。它首先初始化一个堆栈 s
,然后遍历弹出序列。对于每个弹出序列的元素,它会将元素依次推入堆栈,然后尝试弹出元素,如果弹出的元素与序列中的元素不匹配,则返回 false
。如果所有的元素都能够正确弹出,并且没有不匹配的情况,则返回 true
,表示这个弹出序列是合法的。