蒜头君的魔法机

蒜头君有一台神奇的魔法机,它能将输入的序列进行一系列复杂的变换,输出原序列的另一种排列方式。蒜头君十分好奇魔法机的工作原理,终于有一天他尝试着把魔法机拆开研究了。

通过一系列复杂的演算,蒜头君终于发现了魔法机的工作原理:其实魔法机就是一个栈,根据栈先进后出的性质,每次一个数字进栈或将栈顶元素弹出,由此可以产生不同的出栈序列,出栈序列就是原序列的另一种排列了。

在研究完原理后,蒜头君凭借记忆很快就把魔法机组装好了。现在蒜头君想测试下魔法机在组装完成后是否出现问题。

首先他将 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;
}
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yitahutu79

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值