【LeetCode】升级打怪之路 Day 11 加餐:单调队列

今日题目:

  • 239. 滑动窗口最大值 | LeetCode

今天学习了单调队列这种特殊的数据结构,思路很新颖,值得学习。

Problem:单调队列 【必会】

与单调栈类似,单调队列也是一种特殊的数据结构,它相比与普通的 queue,增加了一个新的接口 max() 来获取当前队列的最大值

新增的 max() 是我们选用这个数据结构的最重要原因,单调队列不仅仅可以通过 offer()poll() 接口来实现 FIFO 的元素进出顺序,还额外增加了 max() 接口让我们获取到当前队列中的最大元素。

单调队列主要用来解决下面这个场景:我们会时刻向一个集合中增加新元素或减少旧元素,同时每次可以获取到当前这个集合中的最大值。优先级队列也可以满足这个需求,但优先级队列无法满足 FIFO 的元素进出顺序,这也是必须使用单调队列的原因。

假如有一个数组 window,并知道它的最大值是 A,此时向 window 增加一个新元素 B,我们只需要比较 A 和 B 就可以得到当前 window 中的最大值;但如果删除一个旧元素 C,就麻烦了,因为如果这个删除的 C 恰恰就是最大值 A,那么最大值就要重新遍历 window 来寻找了,从而导致复杂度飙升。这就是单调队列所需要解决的难题。

下面看一下单调队列的经典应用:滑动窗口最大值

LC 239. 滑动窗口最大值 【classic】 ⭐⭐⭐⭐⭐

239. 滑动窗口最大值 | LeetCode

如果我们能够实现数据结构“单调队列” MonoQueue,那我们就每次向右滑动我们的窗口时,向 monoQueue 中新增一个窗口右边的新元素,移除一个窗口左边的旧元素,然后调用 max() 接口获取当前窗口的最大值,就可以计算出题目所需要的最终结果。

在这里插入图片描述

所以重点在于如何实现 MonoQueue。

我们需求的关键是:需要能够快速得知当前队列中的最大值。由于窗口滑动时是有顺序的,先进入的元素一定会先出去,所以如果新进入的一个元素,那么比它老的还比它小的那些元素就永远不可能成为当前队列中的最大值了,因为老元素一定会比新元素更早地离开队列。所以,每次在入队一个新元素时,就可以把队列中比他小的元素都抛弃掉了

在这里插入图片描述
如上图,当元素 5 进入队列后,就可以一下子把 4、3、2、1 全给抛弃掉了,因为这些旧元素在队列的时候 5 一定在,所以这些旧元素一定成不了“当前队列的最大值”。

根据以上分析,单调队列 MonoQueue 的实现如下:

class MonoQueue {private Deque<Integer> maxQ = new LinkedList<>();public void offer(int num) {// 将小于 num 的元素全部删除while (!maxQ.isEmpty() && maxQ.getLast() < num) {maxQ.removeLast();}// 将 num 加入队尾maxQ.addLast(num);}public int max() {return maxQ.getFirst();  // 单调队列,队首就是最大元素}public void poll(int n) {if (maxQ.getFirst() == n) {  // 判断需要移除的是否是队首,如果不是的话,就是比队首小还比队首老的元素,已经被移除了,那就啥也不用干maxQ.removeFirst();}}
}

这里有两个易错点:

  • offer() 函数实现中,第一步删掉掉小于 num 的元素,但注意别把等于它的元素删除了,因为如果把相等的元素也删掉的话,实现 poll() 接口时,就不太好判断 队首最大元素 是否就是我们当前需要 poll 的元素了(我们是通过值相等来判断的)
  • 在实现 poll() 函数时,其参数 n 表示期待删除的元素,因为我们这个 MonoQueue 并没有保留全部入队元素,所以当需要删除一个已经被删除的元素时,poll() 接口只需要立刻返回就可以了。

在实现了 MonoQueue 后,我们解决这个问题就容易多了:

    public int[] maxSlidingWindow(int[] nums, int k) {MonoQueue monoQueue = new MonoQueue();List<Integer> result = new ArrayList<>();// 将前 k-1 个元素填充到队列中for (int i = 0; i < k - 1; i++) {monoQueue.offer(nums[i]);}for (int i = k - 1; i < nums.length; i++) {// 加入窗口右边的新元素monoQueue.offer(nums[i]);// 获取窗口内最大元素,并加入到结果集中result.add(monoQueue.max());// 移除窗口左边的旧元素monoQueue.poll(nums[i - k + 1]);}return result.stream().mapToInt(Integer::valueOf).toArray();}

通过这个题,我们可以更加深入地理解单调队列的具体用法。在有些情况下,我们除了在 MonoQueue 里面维护一个 maxQ 之外,还可以额外维护一个标准的 queue,从而对外表现出正常的 offer() 和 poll() 接口。

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

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

相关文章

【NR 定位】3GPP NR Positioning 5G定位标准解读(一)

目录 前言 1. 3GPP规划下的5G技术演进 2. 5G NR定位技术的发展 2.1 Rel-16首次对基于5G的定位技术进行标准化 2.2 Rel-17进一步提升5G定位技术的性能 3. Rel-18 关于5G定位技术的新方向、新进展 3.1 Sidelink高精度定位功能 3.2 针对上述不同用例&#xff0c;3GPP考虑按…

Go-知识简短变量声明

Go-知识简短变量声明 1. 简短变量声明符2. 简短变量赋值可能会重新声明3. 简短变量赋值不能用于函数外部4. 简短变量赋值作用域问题5. 总结 githuio地址&#xff1a;https://a18792721831.github.io/ 1. 简短变量声明符 在Go语言中&#xff0c;可以使用关键字var或直接使用简短…

【STK】手把手教你利用STK进行仿真-STK软件基础02 STK系统的软件界面01 STK的界面窗口组成

STK系统是Windows窗口类型的桌面应用软件,功能非常强大。在一个桌面应用软件中集成了仿真对象管理、仿真对象属性参数、设置、空间场景二三维可视化、场景显示控制欲操作、仿真结果报表定制与分析、对象数据管理、仿真过程控制、外部接口连接和系统集成编程等复杂的功能。 STK…

SpringBoot之Actuator的两种监控模式

SpringBoot之Actuator的两种监控模式 springboot提供了很多的检测端点(Endpoint),但是默认值开启了shutdown的Endpoint&#xff0c;其他默认都是关闭的,可根据需要自行开启 文章目录 SpringBoot之Actuator的两种监控模式1. pom.xml2. 监控模式1. HTTP2. JMX 1. pom.xml <de…

力扣 第 125 场双周赛 解题报告 | 珂学家 | 树形DP + 组合数学

前言 整体评价 T4感觉有简单的方法&#xff0c;无奈树形DP一条路上走到黑了&#xff0c;这场还是有难度的。 T1. 超过阈值的最少操作数 I 思路: 模拟 class Solution {public int minOperations(int[] nums, int k) {return (int)Arrays.stream(nums).filter(x -> x <…

VM虚拟机无法传输文件(更新时间24/3/3)

出现这个问题一般是未安装VMware Tools 以下为手动安装教程及可能出现的问题的解决方法&#xff1a; 1. 准备安装 2.用cmd手动启动安装 3. 安装过程默认即可&#xff0c;直接一直下一步 4.安装完成后会自动重启虚拟机&#xff08;没有的话手动重启即可&#xff09; 5.重启以后…

StarCoder2模型,释放你的大模型编码潜能

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

部署若依前后端分离项目,连接数据库失败

部署若依前后端分离项目&#xff0c;连接数据库失败&#xff0c;异常如下&#xff1a; 解决方案&#xff1a;application配置文件里&#xff0c;连接数据库的参数useSSL的值改为false

leetcode 长度最小的子数组

在本题中&#xff0c;我们可以知道&#xff0c;是要求数组中组成和为target的最小子数组的长度。所以&#xff0c;我们肯定可以想到用两层for循环进行遍历&#xff0c;然后枚举所有的结果进行挑选&#xff0c;但这样时间复杂度过高。 我们可以采用滑动窗口&#xff0c;其实就是…

编写dockerfile挂载卷、数据容器卷

编写dockerfile挂载卷 编写dockerfile文件 [rootwq docker-test-volume]# vim dockerfile1 [rootwq docker-test-volume]# cat dockerfile1 FROM centosVOLUME ["volume01","volume02"]CMD echo "------end------" CMD /bin/bash [rootwq dock…

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 2

#需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; 某企业根据自身业务需求&#…

每日OJ题_牛客_合法括号序列判断

目录 合法括号序列判断 解析代码 合法括号序列判断 合法括号序列判断__牛客网 解析代码 class Parenthesis {public:bool chkParenthesis(string A, int n){if (n & 1) // 如果n是奇数return false;stack<char> st;for (int i 0; i < n; i) {if (A[i] () {s…

笔记本hp6930p安装Android-x86补记

在上一篇日记中&#xff08;笔记本hp6930p安装Android-x86避坑日记-CSDN博客&#xff09;提到hp6930p安装Android-x86-9.0&#xff0c;无法正常启动&#xff0c;本文对此再做尝试&#xff0c;原因是&#xff1a;Android-x86-9.0不支持无线网卡&#xff0c;需要在BIOS中关闭WLAN…

B082-SpringCloud-Eureka

目录 微服务架构与springcloud架构演变为什么使用微服务微服务的通讯方式架构的选择springcloud概述场景模拟之基础架构的搭建模拟微服务之间的服务调用目前远程调用的问题 eureka注册中心的作用注册中心的实现服务提供者注册到注册中心 springcloud基于springboot 微服务架构与…

10 计算机结构

冯诺依曼体系结构 冯诺依曼体系结构&#xff0c;也被称为普林斯顿结构&#xff0c;是一种计算机架构&#xff0c;其核心特点包括将程序指令存储和数据存储合并在一起的存储器结构&#xff0c;程序指令和数据的宽度相同&#xff0c;通常都是16位或32位 我们常见的计算机,笔记本…

在Centos7中用Docker部署gitlab-ce

一、介绍 GitLab Community Edition (GitLab CE) 是一个开源的版本控制系统和协作平台&#xff0c;用于管理和追踪软件开发项目。它提供了一套完整的工具和功能&#xff0c;包括代码托管、版本控制、问题跟踪、持续集成、持续交付和协作功能&#xff0c;使团队能够更加高效地进…

动态规划|【路径问题】|931.下降路径最小和

目录 题目 题目解析 思路 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 代码 题目 931. 下降路径最小和 给你一个 n x n 的 方形 整数数组 matrix &#xff0c;请你找出并返回通过 matrix 的下降路径 的 最小和 。 下降路径 可以从第一行中的任何元素开…

【Vue3】Props的使用详解

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

概率基础——多元正态分布

概率基础——多元正态分布 介绍 多元正态分布是统计学中一种重要的多维概率分布&#xff0c;描述了多个随机变量的联合分布。在多元正态分布中&#xff0c;每个随机变量都服从正态分布&#xff0c;且不同随机变量之间可能存在相关性。本文将以二元标准正态分布为例&#xff0…

多线程JUC 第2季 中断线程

一 中断线程 1.1 中断概念 1.在java中&#xff0c;没有提供一种立即停止一条线程。但却给了停止线程的协商机制-中断。 中断是一种协商机制。中断的过程完全需要程序员自己实现。也即&#xff0c;如果要中断一个线程&#xff0c;你需要手动调用该线程的interrupt()方法&…