蒜头君的魔法机
原创
©著作权归作者所有:来自51CTO博客作者yitahutu79的原创作品,请联系作者获取转载授权,否则将追究法律责任
蒜头君有一台神奇的魔法机,它能将输入的序列进行一系列复杂的变换,输出原序列的另一种排列方式。蒜头君十分好奇魔法机的工作原理,终于有一天他尝试着把魔法机拆开研究了。
通过一系列复杂的演算,蒜头君终于发现了魔法机的工作原理:其实魔法机就是一个栈,根据栈先进后出的性质,每次一个数字进栈或将栈顶元素弹出,由此可以产生不同的出栈序列,出栈序列就是原序列的另一种排列了。
在研究完原理后,蒜头君凭借记忆很快就把魔法机组装好了。现在蒜头君想测试下魔法机在组装完成后是否出现问题。
首先他将 1 到 N 这 N 个数字依次输入魔法机里,然后随机写下一组序列a,现在他想知道能否通过魔法机得到序列a,聪明的你能帮蒜头君算一算吗?
输入格式
输入有两行,第一行是一个正整数 N(1≤N≤100),表示输入魔法机序列的长度,第二行是序列a,共有 N 个整数,表示要得到的目标序列。
序列为 1 到 N 的排列,即序列a长度为 N,保证序列中的整数都不相同,且整数在区间 [1, N] 内。
输出格式
输出一行,如果能通过魔法机得到序列a,则输出YES,否则输出NO。
#include <stdio.h>
#define ERROR 0
#define OK 1
typedef struct Stack{
int *elements;
int max_size, top_index;
}Stack;
void init(Stack *s, int length) {
s->elements = (int *)malloc(sizeof(int) * length);
s->max_size = length;
s->top_index = -1;
}
int push(Stack *s, int element) {
if (s->top_index + 1 >= s->max_size) {
return ERROR;
}
s->top_index++;
s->elements[s->top_index] = element;
return OK;
}
int pop(Stack *s) {
if (s->top_index < 0) {
return ERROR;
}
s->top_index--;
return OK;
}
int top(Stack *s) {
return s->elements[s->top_index];
}
int empty(Stack *s) {
return s->top_index < 0;
}
void clear(Stack *s) {
free(s->elements);
free(s);
}
int main() {
int n,m;
scanf("%d", &n);
Stack *stack = (Stack *)malloc(sizeof(Stack));
init(stack,n);
int flag = 0; //判断i是否减一
/*判断分三种情况:
1.当输入数字m为n时,i自增为n+1,跳出for循环,如果后面还有未输入的数字,将不会进行判断。为了避免出现这种情况,发现i大于n时,i--。
2.在1的基础上,如果后面还有数字且恰好为栈顶元素,pop完之后栈为空,因为此时i=n,所以不会跳出for循环,程序将永远暂停在这一步。为了避免这种情况,加一个if判断,如果栈空,i++,跳出循环。
3.在1的基础上,如果后面还有数字且不是栈顶元素,即错误的栈,同2一样,此时i=n,不会跳出循环,程序在此处暂停。为了避免这种情况,加一个if判断,如果非栈顶元素,i++,跳出循环。注意,此段代码需要加在开头而不能是结尾,这是因为如果后面还有未输入的数字,栈顶元素不等于输入元素,i++的结果就是跳出循环,陷入1的问题。
*/
for (int i = 1; i <= n;) {
scanf("%d", &m);
if (flag && top(stack) != m) {
i++;
}
while (top(stack) < m) {
push(stack, i);
i++;
}
if (flag == 0 && i == n + 1) {
i--;
flag = 1;
}
if (!empty(stack) && top(stack) == m) {
pop(stack);
}
if (flag && empty(stack)) {
i++;
}
}
if (!empty(stack)) printf("NO\n");
else printf("YES\n");
clear(stack);
return 0;
}