【NC14893】栈和排序

文章讲述了如何通过预处理输入数据,计算每个位置之后的最大值,然后使用栈来存储并按照字典序选择最大值元素,从而得到输入序列中字典序最大的序列。代码示例展示了这一过程。
摘要由CSDN通过智能技术生成

题目

栈和排序

栈的使用

思路

假设现在有一个栈,我们往这个栈中放入元素,放入元素的顺序为:

2 1 5 3 4

经过入栈出栈之后要能够得到字典序最大的序列,那就要选择尽可能大的数出栈,并且在这个数之后没有再比它大的数了。

因此,我们预处理输入的数据,将每个位置之后的最大值求出来,得到一个数组,比如上面的输入数据,我么可以得到下面的数组:
5 , 5 , 5 , 4 , 4 , − 1 5, 5, 5, 4, 4, -1 5,5,5,4,4,1

为什么会多一个 − 1 -1 1 出来呢?这是为了方便处理最后一个输入的数的之后的最大值,这道题没说数据范围,保险起见,将 − 1 -1 1 设为整数最小值吧。

当然,第一个最大值 5 5 5 也没什么用,毕竟 n n n 个位置中每个位置之后的最大值个数也只有 n n n 个, n + 1 n+1 n+1 个数组元素也没什么意义,但是为了方便,多开辟一个整数的空间又如何呢?

得出最终思路:

  1. 预处理每个位置之后的最大值,得到最大值数组 m a x max max
  2. 从左往右遍历输入的元素,先将其入栈,然后循环判断当栈不空时栈顶元素是否大于当前位置之后的最大值,如果大于则出栈

代码

#include <limits.h>
#include <stdio.h>

// 这道题并没有说数据个数
// 下面的个数是恰好合适的(经过测试)
#define N 1000005

// 栈和栈顶指针,stk[top - 1]为栈顶元素
int stk[N], top;

int main(void) {
    int n = 0, i = 0;
    scanf("%d", &n);
    int a[n], max[n + 1];
    for (i = 0; i < n; i++) {
        scanf("%d", a + i);
    }
    max[n] = INT_MIN;
    for (i = n - 1; i >= 0; i--) {
        max[i] = max[i + 1] > a[i] ? max[i + 1] : a[i];
    }
    int flag = 0;
    for (i = 0; i < n; i++) {
        // 将当前元素入栈
        stk[top++] = a[i];
        // 如果当前元素(栈顶元素)比其后面的元素都大的话
        // 说明其是当前最大值,应该出栈
        while (top && stk[top - 1] > max[i + 1]) {
            // 注意输出,最后一个元素的后面没有空格
            if (flag) {
                // 不是第一个元素
                printf(" %d", stk[top - 1]);
            } else {
                // 是第一个元素
                printf("%d", stk[top - 1]);
                // 将标志位置位
                flag = 114514;
            }

            // 实际上本题并没有卡这个空格,直接按下面的输出也可以
            // printf("%d ", stk[top - 1]);

            // 出栈
            top--;
        }
    }
    printf("\n");
    return 0;
}

上面的代码有个巧妙之处:当输入的元素都遍历完了,较大的元素都出栈了的时候,此时栈中可能还会剩余一些元素,而这里不必单独将栈中的元素出栈。此时指针恰好指向最大值数组的最后一个元素,这个元素是一个负无穷的值,每一个元素都比它大,所以此时栈中的剩余的元素就顺理成章地全部出栈了。

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

木又可可

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

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

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

打赏作者

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

抵扣说明:

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

余额充值