蓝桥杯每日一题----单调栈和单调队列

news2024/11/28 5:40:04

单调栈和单调队列

单调栈

单调栈即栈内的元素是单调递减或者单调递增的,我们通过一个题目来理解。

单调栈模板题

题目描述

给出项数为 n 的整数数列 a 1 … a n a_1…a_n a1an

定义函数 f ( i ) f(i) f(i)代表数列中第 i 个元素之后第一个大于 a i a_i ai 的元素的下标,即 f ( i ) = m i n i < j < = n , a j > a i j f(i)=min_{i<j<=n,a_j>a_i}{j} f(i)=mini<j<=n,aj>aij。若不存在,则 f ( i ) = 0 f(i)=0 f(i)=0

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

输入格式

第一行一个正整数 n

第二行 n 个正整数 a 1 … a n a_1…a_n a1an

输出格式

一行n个整数表示 f ( 1 ) , f ( 2 ) , … , f ( n ) f(1),f(2),…,f(n) f(1),f(2),,f(n)的值。

题目分析

题目要求第i个数后面第一个比 a [ i ] a[i] a[i]大的数。首先从头遍历数组,将第一个元素入栈,接着遍历下一个元素,假设当前入栈的元素下标为i,当前遍历到了 i + 1 i+1 i+1,如果 a [ i ] > a [ i + 1 ] a[i]>a[i+1] a[i]>a[i+1],那么 a [ i + 1 ] a[i+1] a[i+1]就不入栈接着向后遍历,如果 a [ i ] < a i + 1 a[i]<ai+1 a[i]<ai+1,那么 a [ i + 1 ] a[i+1] a[i+1]入栈,也就是说栈中的元素是单调递增的。入栈入的是数组的下标,那么在遍历数组的过程中第 i i i个数后面第一个比 a [ i ] a[i] a[i]大的数也就是遍历到 i i i后,后面第一个入栈的元素对应的值。但是什么时候会有第一个元素入栈,这个不好判断。

换个思路,假设我们是找 i i i左边第一个比 i i i小的数字,从头开始遍历数组,将第一个元素入栈,接着遍历下一个元素,假设当前入栈的元素下标为 i i i,当前遍历到了 i + 1 i+1 i+1,如果 a [ i + 1 ] > = a [ i ] a[i+1]>=a[i] a[i+1]>=a[i],则将 a [ i ] a[i] a[i]从栈中弹出,因为 a [ i + 1 ] a[i+1] a[i+1] a [ i ] a[i] a[i]的右边,对于求左边第一个比 a [ i + 2 ] a[i+2] a[i+2]大的数字,如果 a [ i ] > a [ i + 2 ] a[i]>a[i+2] a[i]>a[i+2],必然会有 a [ i + 1 ] > a [ i + 2 ] a[i+1]>a[i+2] a[i+1]>a[i+2],而 a [ i + 1 ] a[i+1] a[i+1]从左边更靠近 a [ i + 2 ] a[i+2] a[i+2],所以它会成为答案,也就是只要 a [ i + 1 ] a[i+1] a[i+1]在这里, a [ i ] a[i] a[i]永远不会成为答案,所以直接弹出就行了。那么最后栈顶的元素要么为空要么大于 a [ i + 1 ] a[i+1] a[i+1],并且是从 a [ i + 1 ] a[i+1] a[i+1]往左数第一个大于 a [ i + 1 ] a[i+1] a[i+1]的数字,所以栈顶元素即为我们想要的答案。

上述思路用一个图来表示,1,2,3,4,5表示的是数组下标,矩形的高度表示的是数组中值的大小,值越大,矩形越高。

当遍历到3的时候,2比3小,所以要从栈里面弹出,后续遍历到4,即便2要比4大,但是因为3的存在只要2符合条件3一定符合条件,但是3要比2更靠近4,也就是更靠近后面的数,所以3永远不会成为答案,把3弹出栈没有问题。遍历到5的时候,虽然3要比4大,也比5大,但是4比5大且更靠近5,所以4是答案。而如果5大于4小于3时,3又会成为答案,所以此时无论是4还是3都有可能成为答案,所以他们留在栈中。

换个形象点的方式,就是站在4上向左看,比3小的数字一定会被3挡住,所以从栈中拿掉就可以了,比如站在4中向左看,只能看到1和3,此时栈中也就只剩下了1和3。站在5中向左看,可以看见1,3,4。

刚刚讲的是求一个数字左边第一小的数字,但是题目要求的是右边第一小的数字,那么只需要对原数组倒序遍历就是求左边第一小的数字了。

题目代码

package 单调队列和单调栈;
import java.util.Scanner;
import java.util.Stack;
public class 单调栈模板 {
public static void main(String[] args) {
	Scanner scanner = new Scanner(System.in);
	int n = scanner.nextInt();
	int a[] = new int[n+1];
	int f[] = new int[n+1];
	for(int i = 1;i <= n;i++) a[i] = scanner.nextInt();
	Stack<Integer> stack = new Stack<Integer>();
	for(int i = n;i > 0;i--) {
		while(!stack.isEmpty()&&a[stack.peek()]<=a[i]) stack.pop();
		if(!stack.isEmpty())
		       f[i] = stack.peek();
		stack.push(i);
	}
	for(int i = 1;i <= n;i++)
	     System.out.print(f[i] + " ");
}
}

ps:感觉洛谷对非c++不太友好,很容易超时或者超内存,这个代码就有几个样例超内存了。

单调队列实现滑动窗口

单调栈值从栈顶弹元素和进元素,单调队列从队头弹元素,从队尾进元素。

单调队列模板

题目描述

有一个长为 n 的序列 a,以及一个大小为 k 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如,对于序列 [ 1 , 3 , − 1 , − 3 , 5 , 3 , 6 , 7 ] [1,3,−1,−3,5,3,6,7] [1,3,1,3,5,3,6,7]以及 k=3,有如下过程:

输入格式

输入一共有两行,第一行有两个正整数 n,k。 第二行 n 个整数,表示序列 a

输出格式

输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值

题目分析

用队列来模拟一下滑动窗口的过程。两个判断

第一个判断是否还在窗口内,因为随着窗口的滑动必然会有一些数字已经离开了窗口,这个时候就要从队列里面删掉。

第二个判断是否有无效数字。对于求最大值的队列来说,假设窗口内的数字是[1,2,1],那么第一个数字1可以提早删掉,因为此时的2是窗口内的最大值并且只要第一个1没有被移出窗口那么2必然也还在,也就是第一个1受2的“压制”永远不会成为窗口内的最大值,直接删掉就可以了。变成了[2,1],那么此时剩下的这个1需要删掉吗?不能删掉,因为数字2会比1先离开窗口,当2离开窗口后,1仍然有机会成为最大值。也就是说这里存的应该是一个单调递减序列,当前待入队数字比队尾数字大,队尾数字就出队。

那么最大值在哪?单调递减序列,最大值自然是第一个数字也就是队头元素。

同样队列里面存的是数组的下标,因为我可以通过数组下标快速判断数字是否还在窗口内,假设当前数字下标为5,窗口大小为3,那么下标小于等于5-3=2的直接出队。

求最小值也是同样的分析方式。

题目代码

package 单调队列和单调栈;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;

public class 单调队列模板 {
public static void main(String[] args) throws IOException {
	Scanner scanner = new Scanner(System.in);
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	String[] strings = br.readLine().split(" ");
	int n = Integer.parseInt(strings[0]);
	int k = Integer.parseInt(strings[1]);
	int a[] = new int[n+1];
	int max[] = new int[n+1];
	int min[] = new int[n+1];
	strings = br.readLine().split(" ");
	for(int i = 1;i <= n;i++) a[i] = Integer.parseInt(strings[i-1]);
	Deque<Integer> qDeque = new ArrayDeque<Integer>();
	for(int i = 1;i <= n;i++) {
		while(!qDeque.isEmpty()&&i-qDeque.peekFirst()>=k) {
			qDeque.pollFirst();
		}
		while(!qDeque.isEmpty()&&a[qDeque.peekLast()]<=a[i]) {
			qDeque.pollLast();
		}
		qDeque.addLast(i);
		max[i] = a[qDeque.peekFirst()];
	}
	qDeque.clear();
	for(int i = 1;i <= n;i++) {
		while(!qDeque.isEmpty()&&i-qDeque.peekFirst()>=k) qDeque.pollFirst();
		while(!qDeque.isEmpty()&&a[qDeque.peekLast()]>=a[i]) qDeque.pollLast();
		qDeque.addLast(i);
		if(i>=k)
		min[i] = a[qDeque.peekFirst()];
	}
	for(int i = k;i <= n;i++)
		 System.out.print(min[i] + " ");
	System.out.println();
	for(int i = k;i <= n;i++)
		 System.out.print(max[i] + " ");
}
}

ps:洛谷提交会超时

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1450601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓游戏开发框架应用场景以及优劣分析

一、引言 在移动游戏开发领域&#xff0c;选择合适的开发框架是项目成功的关键因素之一。特别是对于安卓平台&#xff0c;由于其开放性和庞大的用户基础&#xff0c;不同的游戏开发框架应运而生&#xff0c;旨在帮助开发者高效地构建游戏应用。以下是一些流行的安卓游戏开发框架…

OpenAI全新发布文生视频模型Sora - 现实,不存在了

OpenAI&#xff0c;发他们的文生视频大模型&#xff0c;Sora了。。。。。 而且&#xff0c;是强到&#xff0c;能震惊我一万年的程度。。。 https://openai.com/sora 如果非要用三个词来总结Sora&#xff0c;那就是“60s超长长度”、“单视频多角度镜头”和“世界模型” &am…

五、DataX源码分析、性能参数优化

DataX源码分析 一、总体流程二、程序入口1.datax.py2.com.alibaba.datax.core.Engine.java3.切分的逻辑并发数的确认 3.调度3.1 确定组数和分组算法3.2 数据传输 三、DataX性能优化1.关键参数2.优化&#xff1a;提升每个 channel 的速度3.优化&#xff1a;提升 DataX Job 内 Ch…

SpringBoot3 + Vue3 由浅入深的交互 基础交互教学

说明&#xff1a;这篇文章是适用于已经学过SpringBoot3和Vue3理论知识&#xff0c;但不会具体如何实操的过程的朋友&#xff0c;那么我将手把手从教大家从后端与前端交互的过程教学。 目录 一、创建一个SpringBoot3项目的和Vue3项目并进行配置 1.1后端配置: 1.1.1applicatio…

php基础学习之作用域和静态变量

作用域 变量&#xff08;常量&#xff09;能够被访问的区域&#xff0c;变量可以在常规代码中定义&#xff0c;也可以在函数内部定义 变量的作用域 在 PHP 中作用域严格来说分为两种&#xff0c;但是 PHP内部还定义一些在严格意义之外的一种&#xff0c;所以总共算三种—— 局部…

紫微斗数双星组合:廉贞天相在子午

文章目录 前言内容总结 前言 紫微斗数双星组合&#xff1a;廉贞天相在子午 内容 紫微斗数双星组合&#xff1a;廉贞天相在子午 性格分析 廉贞星最喜天相星同度来制其恶&#xff0c;因天相星之水可剋制廉贞星之火。廉贞星最喜天相星同度来制其恶&#xff0c;使廉贞星变为较温…

MySQL 基础知识(六)之数据查询(二)

目录 6 数值型函数 7 字符串函数 8 流程控制函数 9 聚合函数 10 分组查询 (group by) 11 分组过滤 (having) 12 限定查询 (limit) 13 多表查询 13.1 连接条件关键词 (on、using) 13.2 连接算法 13.3 交叉连接 (cross join) 13.4 内连接 (inner join) 13.5 外连接 …

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱6(附带项目源码)

效果演示 文章目录 效果演示系列目录前言存储加载物品信息源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中&#xff0c;我们将探索如何用unity制作一个3D背包、库存、制作、快…

【leetcode994】腐烂的橘子(BFS)

文章目录 一、题目二、思路三、代码 一、题目 二、思路 首先将所有烂橘子入队&#xff0c;然后常规BFS遍历&#xff0c;注意while的截止条件除了队列为空&#xff0c;新鲜橘子数量大于0&#xff08;没新鲜橘子也没必要继续遍历&#xff0c;保证时间计算的正确性&#xff09;&a…

Compose自定义动画API指南

很多动画API都可以自定义其参数达到不同的效果&#xff0c;Compose也提供了相应的API供开发者进行自定义动画规范。 AnimationSpec 主要用存储动画规格&#xff0c;可以自定义动画的行为&#xff0c;在animate*AsState和updateTransition函数中&#xff0c;此函数默认参数为s…

机器学习——聚类问题

&#x1f4d5;参考&#xff1a;西瓜书ysu老师课件博客&#xff08;3&#xff09;聚类算法之DBSCAN算法 - 知乎 (zhihu.com) 目录 1.聚类任务 2.聚类算法的实现 2.1 划分式聚类方法 2.1.1 k均值算法 k均值算法基本原理&#xff1a; k均值算法算法流程&#xff1a; 2.2 基于…

语言与真实世界的关系(超级语言生成能力将促进世界深刻变化)

语言与真实世界之间存在着紧密且复杂的关系。在人类社会中&#xff0c;语言是认知、表达和交流现实世界的主要工具&#xff0c;它帮助我们构建并理解周围环境&#xff0c;并将我们的思维和经验概念化。 1. 符号与指代&#xff1a; 语言是一种符号系统&#xff0c;通过词汇、句…

SG3225EEN晶体振荡器规格书

SG3225EEN 晶振是EPSON/爱普生的一款额定频率25 MHz至500 MHz的石英晶体振荡器&#xff0c;6脚贴片&#xff0c;LV-PECL输出&#xff0c;3225封装常规有源晶振&#xff0c;具有小尺寸&#xff0c;轻薄型&#xff0c;高稳定性&#xff0c;低相位抖动&#xff0c;低电源电压&…

17.3.1.2 曝光

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 基本算法&#xff1a;先定义一个阈值&#xff0c;通常取得是128 原图像&#xff1a;颜色值color&#xff08;R&#xff0c;G&#…

OpenTitan- 开源安全芯片横空出世

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【前端web入门第六天】02 flex布局

文章目录 Flex布局1.Flex组成2.主轴与侧轴对齐方式2.1 主轴对齐方式(横轴)2.2 侧轴对齐方式 (纵轴)2.3 修改主轴方向 3.弹性伸缩比4.弹性换行与行对齐方式4.1 弹性换行4.2 行对齐方式 Flex布局 1.Flex组成 设置方式:给父元素设置display: flex&#xff0c;子元素可以自动挤压…

找负环(图论基础)

文章目录 负环spfa找负环方法一方法二实际效果 负环 环内路径上的权值和为负。 spfa找负环 两种基本的方法 统计每一个点的入队次数&#xff0c;如果一个点入队了n次&#xff0c;则说明存在负环统计当前每个点中的最短路中所包含的边数&#xff0c;如果当前某个点的最短路所…

【C++】---类和对象(上)入门

一、类的定义 1.那么众所周知&#xff0c;C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解的步骤&#xff0c;通过函数的调用来逐步解决问题 2.而C是基于面向对象的&#xff0c;关注的是对象&#xff0c;将一件事情拆分成不同的对象&#xff0c;靠对象之间交…

【自然语言处理】:实验1布置,Word2VecTranE的实现

清华大学驭风计划 因为篇幅原因实验答案分开上传&#xff0c;答案链接http://t.csdnimg.cn/5cyMG 如果需要详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢迎私信博主&#xff0c;大家可以相互讨论交流哟~~ 实验1&#xff1a; Word2Vec&TranE的…

使用HTML、CSS和JavaScript构建响应式企业官网

使用HTML、CSS和JavaScript构建响应式企业官网&#xff0c;web网页设计与制作-htmlcssjs实现企业官网展示。 页面效果展示 pc端和移动端 动态演示 文件目录 assets文件夹&#xff1a;静态资源目录&#xff0c;主要存放css、fonts、images、js等静态资源文件&#xff1b; fa…