当前位置: 首页 > article >正文

【LeetCode Hot 100】滑动窗口最大值——多种解法深度解析

题目描述题目链接LeetCode 239. 滑动窗口最大值给你一个整数数组nums有一个大小为k的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k个数字。滑动窗口每次只向右移动一位。返回每个滑动窗口中的最大值。示例text输入nums [1,3,-1,-3,5,3,6,7], k 3 输出[3,3,5,5,6,7] 解释 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7解法一暴力法最直观但超时思路最直接的想法遍历每个窗口在每个窗口中找最大值。代码实现javapublic int[] maxSlidingWindow(int[] nums, int k) { int n nums.length; if (n 0 || k 0) return new int[0]; int[] result new int[n - k 1]; for (int i 0; i n - k; i) { int max nums[i]; for (int j i 1; j i k; j) { max Math.max(max, nums[j]); } result[i] max; } return result; }复杂度分析时间复杂度O(n×k)每个窗口都要遍历k个元素空间复杂度O(1)除结果数组外不需要额外空间优缺点✅ 思路简单易于理解❌ 当k接近n时时间复杂度接近O(n²)在LeetCode上会超时解法二优先队列最大堆思路使用最大堆PriorityQueue来维护窗口内的元素。堆顶始终是最大值。窗口滑动时添加新元素移除离开窗口的元素。代码实现javapublic int[] maxSlidingWindow(int[] nums, int k) { int n nums.length; if (n 0 || k 0) return new int[0]; int[] result new int[n - k 1]; // 最大堆存储数组元素 PriorityQueueInteger maxHeap new PriorityQueue((a, b) - b - a); // 初始化第一个窗口 for (int i 0; i k; i) { maxHeap.offer(nums[i]); } result[0] maxHeap.peek(); // 滑动窗口 for (int i k; i n; i) { // 移除离开窗口的元素注意这里只能移除一个如果有重复值会出问题 maxHeap.remove(nums[i - k]); // 添加新元素 maxHeap.offer(nums[i]); // 记录当前窗口最大值 result[i - k 1] maxHeap.peek(); } return result; }复杂度分析时间复杂度O(n log k)每次添加/删除操作都是O(log k)空间复杂度O(k)堆的大小为k优缺点✅ 实现相对简单❌remove()操作是O(k)的实际复杂度更高❌ 无法处理重复元素会误删优化版本存储索引javapublic int[] maxSlidingWindow(int[] nums, int k) { int n nums.length; int[] result new int[n - k 1]; // 存储索引的最大堆 PriorityQueueInteger maxHeap new PriorityQueue((a, b) - nums[b] - nums[a]); for (int i 0; i n; i) { // 移除不在窗口内的索引 while (!maxHeap.isEmpty() maxHeap.peek() i - k) { maxHeap.poll(); } maxHeap.offer(i); if (i k - 1) { result[i - k 1] nums[maxHeap.peek()]; } } return result; }解法三双端队列单调队列⭐ 最优解核心思想维护一个单调递减的双端队列队首始终是当前窗口的最大值。关键点队列中存储数组索引而不是值方便判断是否离开窗口保持队列单调递减新元素从队尾进入移除所有比它小的元素移除离开窗口的元素如果队首索引 i - k说明已不在窗口内图解过程以nums [1,3,-1,-3,5,3,6,7], k 3为例texti0: 队列空 → 加入0 → [0] i1: nums[1]3, 比队尾的1大 → 移除0 → 加入1 → [1] i2: nums[2]-1, 比队尾的3小 → 加入2 → [1,2] 窗口形成result[0]nums[1]3 i3: 加入-3 → [1,2,3], 队首1仍在窗口内 → result[1]3 i4: 加入5 → 移除3,2,1 → [4] → result[2]5 i5: 加入3 → [4,5] → result[3]5 i6: 加入6 → 移除5,4 → [6] → result[4]6 i7: 加入7 → 移除6 → [7] → result[5]7代码实现javapublic int[] maxSlidingWindow(int[] nums, int k) { if (nums null || nums.length 0 || k 0) { return new int[0]; } int n nums.length; int[] result new int[n - k 1]; DequeInteger deque new ArrayDeque(); // 存储索引 for (int i 0; i n; i) { // 1. 移除队列中所有小于当前元素的值维护单调递减 while (!deque.isEmpty() nums[deque.peekLast()] nums[i]) { deque.pollLast(); } // 2. 将当前元素索引加入队尾 deque.offerLast(i); // 3. 如果队首元素已离开窗口移除它 if (deque.peekFirst() i - k) { deque.pollFirst(); } // 4. 当窗口形成后记录最大值 if (i k - 1) { result[i - k 1] nums[deque.peekFirst()]; } } return result; }为什么用而不是javawhile (!deque.isEmpty() nums[deque.peekLast()] nums[i])使用可以保证队列严格递减不会保留相等值的旧元素。因为新来的相等元素会取代旧元素的位置这样队列中最多只有一个重复值避免窗口滑动时误删问题。复杂度分析时间复杂度O(n)每个元素最多入队和出队一次空间复杂度O(k)队列最多存储k个元素优缺点✅ 时间复杂度最优O(n)✅ 代码简洁优雅✅ 每个元素只处理一次⚠️ 需要理解单调队列的思想解法四动态规划分块法思路将数组分成大小为k的块预处理每个块的前缀最大值和后缀最大值然后每个窗口的最大值就是左右两部分的最大值的较大者。代码实现javapublic int[] maxSlidingWindow(int[] nums, int k) { int n nums.length; if (n 0 || k 0) return new int[0]; int[] leftMax new int[n]; int[] rightMax new int[n]; // 计算从左到右每个块的前缀最大值 for (int i 0; i n; i) { if (i % k 0) { leftMax[i] nums[i]; } else { leftMax[i] Math.max(leftMax[i - 1], nums[i]); } } // 计算从右到左每个块的后缀最大值 for (int i n - 1; i 0; i--) { if (i n - 1 || (i 1) % k 0) { rightMax[i] nums[i]; } else { rightMax[i] Math.max(rightMax[i 1], nums[i]); } } // 每个窗口的最大值 max(窗口右部分的前缀最大, 窗口左部分的后缀最大) int[] result new int[n - k 1]; for (int i 0; i n - k; i) { result[i] Math.max(rightMax[i], leftMax[i k - 1]); } return result; }复杂度分析时间复杂度O(n)空间复杂度O(n)优缺点✅ 时间复杂度也是O(n)✅ 思路巧妙利用分块思想❌ 需要额外的O(n)空间❌ 理解起来比单调队列复杂解法对比总结解法时间复杂度空间复杂度优点缺点暴力法O(n×k)O(1)简单直观会超时优先队列O(n log k)O(k)实现简单remove操作慢单调队列O(n)O(k)最优解需要理解思想分块法O(n)O(n)另一种O(n)解法空间占用大推荐解法面试推荐单调队列法时间复杂度最优 O(n)空间复杂度 O(k)代码简洁优雅是这道题的标准解法常见问题答疑Q1为什么单调队列中存储索引而不是值A存储索引可以精确判断元素是否还在窗口内通过比较i - k避免重复值带来的歧义。Q2队列为什么要保持单调递减A保证队首始终是当前窗口的最大值。如果新元素比队尾大那么队尾元素永远不可能成为最大值因为新元素更大且更晚离开窗口可以直接淘汰。Q3处理重复元素时需要注意什么A使用而不是来比较这样新来的重复值会取代旧值避免窗口滑动时误删。相关题目推荐LeetCode 76. 最小覆盖子串LeetCode 1425. 带限制的子序列和LeetCode 1696. 跳跃游戏 VI总结滑动窗口最大值是一道经典的单调队列应用题。掌握单调队列的思想不仅能解决这道题还能解决一系列滑动窗口求最值的问题。核心要点使用双端队列维护单调递减序列队列存储索引而非值每次滑动时移除过期的队首、移除比新元素小的队尾、加入新元素队首就是当前窗口的最大值参考链接题目链接LeetCode 239. 滑动窗口最大值官方题解如果这篇文章对你有帮助欢迎点赞、收藏、关注

相关文章:

【LeetCode Hot 100】滑动窗口最大值——多种解法深度解析

题目描述 题目链接:LeetCode 239. 滑动窗口最大值 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回每个滑动窗口中的最大值。 示例&am…...

弹幕格式转换难题?用DanmakuFactory一键解决XML到ASS的专业转换

弹幕格式转换难题?用DanmakuFactory一键解决XML到ASS的专业转换 【免费下载链接】DanmakuFactory 支持特殊弹幕的xml转ass格式转换工具 项目地址: https://gitcode.com/gh_mirrors/da/DanmakuFactory 在当今的视频创作和观看生态中,弹幕已经成为不…...

ERTEC 系列 PROFINET 芯片级硬件过滤器分析桌

一、语言特性:Java 26 与模式匹配进化 1.1 Java 26 语言级别支持 IDEA 2026.1 EAP 最引人注目的变化之一,就是新增 Java 26 语言级别支持。这意味着开发者可以提前体验和测试即将在 JDK 26 中正式发布的语言特性。 其中最重要的变化是对 JEP 530 的全面支…...

【服务出错问题排查记录】从一个“点击失败”开始:为什么“系统异常”其实是最差的错误设计

一、问题起点:一次“无信息”的失败 ​ 那天我在页面上点击一个功能按钮,预期是触发一次 URL 分析任务。但页面只返回了一句:❗“系统异常,请稍后重试”。​ 没有错误详情,没有接口信息,也没有任何可追踪线…...

FastECompass:嵌入式轻量级倾角补偿电子罗盘算法库

1. FastECompass 库概述FastECompass 是一个专为嵌入式系统设计的轻量级电子罗盘(e-compass)算法库,核心目标是在资源受限的微控制器上实时、高效地解算三维姿态角:俯仰角(Pitch)、横滚角(Roll&…...

008、OpenClaw TTS 声学模型实战:训练数据准备与配置解析

上周调一个长句合成,输出音频在中段突然出现音调断裂,像是两个不同人在交替发音。频谱图上一看,隐状态在某个音素边界处发生了跳变。问题最终追溯到训练数据里同一说话人的音频存在采样率混用——部分文件是16kHz,另一些却是22.05kHz。预处理脚本没做统一重采样,导致模型在…...

语言的边界,与软件的命运秃

1. 引入 在现代 AI 工程中,Hugging Face 的 tokenizers 库已成为分词器的事实标准。不过 Hugging Face 的 tokenizers 是用 Rust 来实现的,官方只提供了 python 和 node 的绑定实现。要实现与 Hugging Face tokenizers 相同的行为,最好的办法…...

大模型推理延迟突增2300ms?立刻检查这7个负载均衡配置陷阱(含Nginx+Kong+Traefik三框架避坑checklist)

第一章:大模型工程化负载均衡策略优化 2026奇点智能技术大会(https://ml-summit.org) 在大模型推理服务规模化部署中,传统轮询或随机调度策略常导致GPU显存碎片化、请求延迟抖动加剧及节点间负载严重失衡。工程化负载均衡需兼顾请求语义特征&#xff0…...

html页面间调用

一、简单情况1、父页面通过iframe套子页面情况子页面通过window.parent调用父页面的函数2、多层嵌套window.top找到最顶层3、父界面通过open打开子界面子界面通过window.opener得到父界面二、复杂情况根据上述关系,进行各种组合,例如window.top.opener举…...

RT-Thread Studio配置避坑:手把手教你为WCH CH32V303工程正确指定GCC12工具链路径

RT-Thread Studio配置避坑:手把手教你为WCH CH32V303工程正确指定GCC12工具链路径 在嵌入式开发中,选择合适的工具链往往能显著提升开发效率和代码质量。对于使用WCH CH32V303这类RISC-V架构MCU的开发者来说,GCC12工具链带来的性能优化和代码…...

忘记文件名也能秒找文件!免索引全文搜索神器 FileLocator Pro v9.3.3560 多语便携版,支持Word/PDF/压缩包内容检索,助力高效办公

日常工作中,我们可能都有过这样的经历:记得文档里的某句话或某个数据,却想不起文件名,也不知道存在哪个文件夹里。Windows自带的搜索功能按文件名查找还可以,但按内容搜索时速度较慢,而且很多格式的文件搜不…...

M3GIM2:面向mbed OS的3G IoT模组轻量级驱动库

1. 项目概述M3GIM2 是专为 mbed OS 平台设计的轻量级驱动库,面向日本 Tabrain 公司推出的3GIM(3G IoT Module)通信模组。该模组定位于工业级低功耗物联网终端,支持 WCDMA/HSDPA(UMTS Band I/VI/VIII)、内置…...

记录一个使用AI开发企业官网的思路

背景 今天在开发一个企业官网,想使用AI来开发,记录一下AI系统提示词,供大家学习。 AI提示词如下 角色:你是一位资深的全栈开发专家,精通Vue 3.0技术栈和现代UI/UX设计,善于将品牌故事转化为具有感染力的数字…...

数模加油站:以数为翼,为梦想加油 —— 赋能每一位建模者的成长之路

数模加油站隶属于合肥科思通途教育科技有限公司,脱胎于2018年成立的睿森科研,深耕教育科技赛道,专注于数学建模服务领域,以专业之力搭建优质服务平台。品牌秉持“让数学建模触手可及,让每一份努力都有回响”的核心价值…...

大模型到底是啥?运维人分钟搞懂(不用数学)缎

1. 流图:数据的河流 如果把传统的堆叠面积图想象成一块块整齐堆叠的积木,那么流图就像一条蜿蜒流淌的河流,河道的宽窄变化自然流畅,波峰波谷过渡平滑。 它特别适合展示多个类别数据随时间的变化趋势,尤其是当你想强调整…...

Spring with AI (): 搜索扩展——向量数据库与RAG(下)僖

. GIF文件结构 相比于 WAV 文件的简单粗暴,GIF 的结构要精密得多,因为它天生是为了网络传输而设计的(包含了压缩机制)。 当我们用二进制视角观察 GIF 时,它是由一个个 数据块(Block) 组成的&…...

从ViT到Swin:手把手教你理解那个让Transformer在CV领域“开窍”的Shifted Windows

从ViT到Swin:揭秘Shifted Windows如何让Transformer在CV领域"开窍" 当Vision Transformer(ViT)首次将自然语言处理领域的Transformer架构引入计算机视觉时,整个AI社区为之振奋。但很快,研究者们发现了一个尴…...

人工智能编程流程技能AI Dev Workflow

AI Dev Workflow(SkillHub) AI Dev Workflow(ClawHub) name: AI Dev Workflow author: 王教成 Wang Jiaocheng (波动几何) description: 此技能提供一个标准化、可复现的AI辅助编程工作流,通过三个有序步骤将模糊想法转…...

性能核弹X4522首发“翻车”不断?赋缘汇全套调教方案出炉:五大旗舰平台稳如泰山,EFVI一键脚本封神!

你是否也经历了这样的至暗时刻? 手握最新的X4522网卡,满心期待性能核弹的爆发,结果刚插上设备就“变哑”?面对Onload驱动报错和复杂的EFVI源码编辑,只能无奈叹息,甚至想把这块“核弹”扔进角落&#xff0c…...

MiniMax M. 发布!Redis 故障排查 + 跨语言重构场景实测,表现如何?确

一、前言:什么是 OFA VQA 模型? OFA(One For All)是字节跳动提出的多模态预训练模型,支持视觉问答、图像描述、图像编辑等多种任务,其中视觉问答(VQA)是最常用的功能之一——输入一张…...

嵌入式OTA封装库:解耦硬件与升级逻辑的生产级抽象层

1. OTAHandler:嵌入式系统OTA能力封装库深度解析1.1 设计定位与工程价值OTAHandler并非一个独立的固件升级协议栈,而是一个面向生产级嵌入式系统的OTA能力抽象层。其核心设计哲学是“解耦”与“可移植”——将底层通信驱动(UART/USB/CAN/Ethe…...

告别Python+Netmiko!Rust+NexusOps如何重塑网络自动化

# 🚀 告别PythonNetmiko!RustNexusOps如何重塑网络自动化> 作者:NexusOps技术团队 | 原创 | 转载请注明出处> 标签:网络自动化、Rust、Netmiko、网络运维、Python## 📋 文章目录- [一、前言:为什么需…...

iarduino I²C赛道模块控制库:面向教育与竞赛的嵌入式功能抽象层

1. 项目概述iarduino_I2C_Track是一款面向教育与竞赛场景的嵌入式 IC 外设控制库,专为 iArduino 系列 IC Flash 赛道模块设计。该库的核心目标是提供统一、可靠、低侵入性的硬件抽象层,使开发者能够以最小的底层细节负担完成对赛道系统中各类执行单元&am…...

CafeIOT嵌入式云连接库:轻量级二进制协议栈设计与ESP32实践

1. 项目概述CafeIOT 是一个面向嵌入式物联网终端的轻量级云连接库,专为 ESP32(及兼容 ESP8266)平台设计,实现设备与 CafeIOT 云平台之间的可靠、低开销 TCP/IP 级通信。尽管其 README 中仅提及 “Esp8266”,但实际工程…...

《YOLOv11 实战:从入门到深度优化》017、模型跟踪与融合:YOLOv11与ByteTrack等算法的结合

017、模型跟踪与融合:YOLOv11与ByteTrack等算法的结合一、从产线误报说起 上周产线反馈了个诡异问题:视频里工人反复搬运同一箱零件,系统却记录成“货物异常消失又出现”。查日志发现检测框ID跳来跳去——典型的跟踪丢失。单纯调高YOLOv11的置…...

2026年“Highcharts vs ECharts”|企业可视化选错图表库,不止是多花成倍成本

在做企业数据可视化时,很多开发者第一反应是:用免费的 ECharts或者用 企业级Highcharts商业版图表库但问题是:这不是“哪个好用”的问题,而是“你未来成本会差多少”的问题。一、一个被低估的决策图表库选择,看起来只是…...

AndroidStudio下载安装

1. 安装Android Studio Custom安装,选择Android虚拟机环境8G 2. 创建一个Android项目 new project empty views activity 3. 新建一个项目后报错 把services.gradle.org/distributions替换成mirrors.cloud.tencent.com/gradle,其余地方不改动&…...

PyCharm 的智能开发助手:提升 Python 编码效率的利器

1. 为什么PyCharm是Python开发者的首选工具 第一次打开PyCharm时,我就被它的智能程度震惊了。作为一个长期使用记事本和基础编辑器写Python的开发者,突然发现代码可以自动补全、错误会被实时标记、函数定义能一键跳转,这种体验就像从自行车换…...

OpenClaw Memory 记忆系统完全指南:文件结构、Heartbeat机制与调教实践

关键词:OpenClaw Memory、AI Agent记忆、本地记忆存储、Heartbeat心跳、USER.md调教一、问题背景:为什么 AI Agent 需要独立的记忆系统 大模型的上下文窗口有限——即使是 200K tokens 的 Claude,关闭窗口后也完全忘记之前的对话。要让 AI Ag…...

袁永福 电子病历,医疗信息化照

在AI辅助开发的语境下,Skill就是一个包含了领域知识、最佳实践、代码模板的知识包。 以"DAO层CRUD生成"为例,一个Skill包含: /mnt/skills/dao-crud/ ├── SKILL.md # 使用说明 │ ├── 何时使用这个Skill │ ├── 输入格…...