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

单调栈和单调队列

单调栈

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

单调栈模板题

题目描述

给出项数为 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.mzph.cn/news/684258.shtml

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

相关文章

Redis面试题整理(持续更新)

1. 缓存穿透&#xff1f; 缓存穿透是指查询一个一定不存在的数据&#xff0c;如果从存储层查不到数据则不写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到 DB 去查询&#xff0c;可能导致DB挂掉&#xff0c;这种情况大概率是遭到了攻击。 解决方案&#xff1a; …

python-分享篇-自定义词云图颜色

文章目录 准备代码效果 准备 运行本程序需要安装第三方模块matplotlib、jieba、wordcloud 和scipy &#xff0c;scipy要求1.0.0版本&#xff0c;否则程序将出现导入错误&#xff1a;ImportError: cannot import name ‘imread’ from ‘scipy.misc’ ImportError: cannot impo…

Linux下的自动化任务与计划任务:让你的系统更智能

在日常的Linux系统管理中&#xff0c;你是否经常需要定时执行某些任务&#xff0c;或者希望在系统启动时自动运行某些脚本&#xff1f;如果是的话&#xff0c;那么自动化任务和计划任务将是你的得力助手。它们可以帮助你提高系统效率、减少人工干预&#xff0c;并确保任务能够按…

【汇编】简单的linux汇编语言程序

一、Linux系统汇编语言 Linux系统上的汇编语言可以使用不同的语法风格&#xff0c;主要包括Intel语法和AT&T语法。这两种语法有各自的特点和风格区别&#xff0c;尽管它们表示的底层机器指令相同。下面分别对两种语法进行简要说明&#xff1a; Intel语法 Intel语法是由I…

有啥办法把百度地图某个点1公里范围内截个图?

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 东方欲晓&#xff0c;莫道君行早。 大家好&#xff0c;我是皮皮。 一、前言 前几天在Python白银交流群【上海新年人】问了一个地图截图的问题&#xff…

找不到目标和方向,怎么办?

现代社会里&#xff0c;许多人常见的症状&#xff0c;就是「空心病」。 什么是空心病呢&#xff1f;类似这样&#xff1a; 我知道要有目标&#xff0c;但我就是不知道想做什么&#xff0c;感觉对一切事物都提不起兴趣&#xff0c;没有动力&#xff0c;怎么办&#xff1f; 这个…

【C语言】socketpair 的系统调用

一、 Linux 内核 4.19socketpair 的系统调用 SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,int __user *, usockvec) {return __sys_socketpair(family, type, protocol, usockvec); } 这段代码定义了一个名为 socketpair 的系统调用。系统调用是操作…

AI算法参数个数本身优化空间

一、背景 AI算法的参数数量并非越多越好&#xff0c;也不是越少越好。参数的数量与模型的复杂度密切相关&#xff1a; 1. 参数多&#xff08;高复杂度模型&#xff09;&#xff1a; - 优点&#xff1a;模型具有更强的表达能力和拟合能力&#xff0c;对于复杂的、非线性的数据分…

C 语言 devc++ 使用 winsock 实现 windows UDP 局域网发送消息

U参考来源 U 这里移植到windows 上 &#xff0c;使用 devc 开发。 服务端代码 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <winsock2.h>int main() {WORD sockVersion MAKEWORD(2, 2);WSAD…

微服务多级缓存

多级缓存 1.什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未命中则查询数据库&#xff0c;如图&#xff1a; 存在下面的问题&#xff1a; •请求要经过Tomcat处理&#xff0c;Tomcat的性能成为整个系统的瓶颈 •Redis缓存…

MATLAB实现朴素贝叶斯分类

朴素贝叶斯&#xff08;Naive Bayes&#xff09;是一种基于贝叶斯定理的分类算法&#xff0c;它假设特征之间相互独立&#xff0c;从而简化了计算复杂性。该算法常用于文本分类、垃圾邮件过滤、情感分析等应用场景。 MATLAB实现鸢尾花数据集分类代码如下&#xff1a; clear lo…

2024 CKS 题库 | 7、Dockerfile检测

不等更新题库 CKS 题库 7、Dockerfile检测 Task 分析和编辑给定的Dockerfile /cks/docker/Dockerfile&#xff08;基于ubuntu:16.04 镜像&#xff09;&#xff0c; 并修复在文件中拥有的突出的安全/最佳实践问题的两个指令。 分析和编辑给定的清单文件 /cks/docker/deployme…

Python·turtle库编程之:怎么画一个五角星?

文章目录 前言源码附&#xff1a; 前言 大家好&#xff0c;我是BoBo仔&#xff0c;这节课我要带来一期turtle库的使用教程——画五角星。话不多说&#xff0c;我们直接上代码。 源码 import turtle as t t.pencolor(yellow) t.fillcolor("yellow") t.penup() t.go…

react 【七】各种hooks的使用/SPA的缺点

文章目录 1、Hook1.1 为什么会出现hook1.2 useState1.3 useEffect1.4 useContext1.5 useReducer1.6 useCallback1.7 useMemo1.8 useRef1.8.1 ref绑定dom1.8.2 ref解决闭包缺陷 1.9 useImperativeHandle1.10 useLayoutEffect1.11 自定义Hook1.11.1 什么是自定义Hook1.11.2 Conte…

Rust 数据结构与算法:3栈:用栈实现符号匹配

1、符号匹配 如&#xff1a; (56)(78)/(43)、{ { ( [ ] [ ])}}、(ab)(c*d)func() 等各类语句的符号匹配。 这里我们关注的不是数字而是括号&#xff0c;因为括号更改了操作优先级&#xff0c;限定了语言的语义&#xff0c;这是非常重要的。如果括号不完整&#xff0c;那么整个…

【Deep Learning 1】神经网络的搭建

&#x1f31e;欢迎来到PyTorch的世界 &#x1f308;博客主页&#xff1a;卿云阁 &#x1f48c;欢迎关注&#x1f389;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f31f;本文由卿云阁原创&#xff01; &#x1f4c6;首发时间&#xff1a;&#x1f339;2024年2月16日&a…

消息队列RabbitMQ-使用过程中面临的问题与解决思路

消息队列在使用过程中会出现很多问题 首先就是消息的可靠性&#xff0c;也就是消息从发送到消费者接收&#xff0c;消息在这中间过程中可能会丢失 生产者到交换机的过程、交换机到队列的过程、消息队列中、消费者接收消息的过程中&#xff0c;这些过程中消息都可能会丢失。 …

gem5 garnet 合成流量: packet注入流程

代码流程 下图就是全部. 剩下文字部分是细节补充,但是内容不变: bash调用python,用python配置好configuration, 一个cpu每个tick运行一次,requestport发出pkt. bash 启动 python文件并配置 ./build/NULL/gem5.debug configs/example/garnet_synth_traffic.py \--num-cpus…

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

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

vue-组件组成和组件通信(四)

组件的三大组成部分 (结构/样式/逻辑) scoped样式冲突 默认情况&#xff1a;写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。 1. 全局样式: 默认组件中的样式会作用到全局 2. 局部样式: 可以给组件加上 scoped 属性, 可以让样式只作用于当前组…