算法刷题之栈系列P5788-单调栈

题目描述


给出项数为 n的整数数列 a 1 … n a_{1 … n} a1n

定义函数 f(i) 代表数列中第 ii 个元素之后第一个大于 a**i 的元素的下标,若不存在,则 f(i)=0。

试求出 f*(1…*n)。

CSDN显示可能有问题,不允许外链转存,大家可以在我的博客中阅读:My Blog

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fkmvLtEX-1628094671699)(https://z3.ax1x.com/2021/08/05/fV9nYV.png)]

思路解析


实际上这一道题和前面那一道日志分析是非常像的,不过这里这个需要我们先将所有的数字都读进a[3000005],读进来之后从后往前开始,定义一个辅助数组b[3000005]用来存储相同位置的数比他大的第一个数的索引值,从最后一个数开始,最后一个数为0,然后往前,随意一个数a[i]先判断是否它比后面第一个数a[i+1]大,如果比后面第一个数a[i+1]小,那么那个辅助数组只需在该位置存储该位置的索引 i+1 就行;如果它比它后面第一个数a[i+1]大或是相等,那么就找比它后面那个数a[i+1]还大的数a[b[i+1]],由于是从后往前进行的,这个b[i+1]已经求出来了,如果我们的a[b[i+1]],仍然不比a[i]大,那么就继续找a[b[b[i+1]]], 哈哈哈,有点套娃的感觉了,实际上就是找比a[b[i+1]]还大的第一个数,这么依次找下去,直到找到一个比a[i]大的数,将其索引存储到b[i]上, 或者直到找到一个b[j]为0,那么说明a[i]是目前最大数,没有比它更大的数,那么对应的b[i]就为0。

代码


#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

int a[3000002];   // 用来存储数据
int b[3000002];   // 用来存储我们的答案

int main()
{
	int n;  // 总共的个数
	scanf("%d", &n);

	// 读取数据
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	b[n] = 0;
	for (int i = n - 1; i >= 1; i--)
	{
		if (a[i] < a[i + 1])   // 如果后面的第一个数正好比他大
			b[i] = i + 1;
		else
		{
			int next = b[i + 1];
			while (a[i] >= a[next] && next != 0)  // // 如果后面第一个数没有比他更大的数,那么直接赋值为0,否则就一直找接下来的索引直到找到0或者找到合适的数为止
				next = b[next];
			
			b[i] = next;
		}
	}

	for (int i = 1; i <= n; i++)
		printf("%d ", b[i]);

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值