力扣hot100:滑动窗口最大值优化策略及思路讲解(239)

记录一下今天完成的算法题,虽然这个难度是困难,但感觉没有那个560.和为k的子数组和难想,这个题主要就前期遇到个优先队列,因为之前没用过,不太熟悉,剩下的思路感觉都属于正常难度
问题描述

原始思路:优先队列(最大堆)

原始代码使用最大堆(PriorityQueue)存储元素值及其索引,堆顶始终是当前窗口的最大值。但原始代码存在逻辑错误,修正后的代码如下:

import java.util.PriorityQueue;public class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 0) return new int[0];PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> b[0] - a[0]); // 最大堆// 初始化第一个窗口for (int i = 0; i < k; i++) {pq.offer(new int[]{nums[i], i});}int[] result = new int[nums.length - k + 1];result[0] = pq.peek()[0]; // 第一个窗口的最大值// 滑动窗口for (int i = k; i < nums.length; i++) {pq.offer(new int[]{nums[i], i}); // 1. 加入新元素while (pq.peek()[1] < i - k + 1) {  // 2. 弹出不在窗口内的元素pq.poll();}result[i - k + 1] = pq.peek()[0]; // 3. 记录当前窗口最大值}return result;}
}

核心逻辑
  1. 初始化堆:将第一个窗口的元素 [值, 索引] 加入最大堆。
  2. 滑动窗口
    • 加入新元素:将窗口右侧新元素加入堆。
    • 清理无效元素:弹出堆顶所有索引小于 i - k + 1 的元素(这些元素已离开窗口)。
    • 记录最大值:堆顶元素即为当前窗口最大值。

复杂度分析
  • 时间复杂度O(n log n) 每个元素入堆和出堆需 O(log n),最坏情况下(如单调递增数组)堆中元素累积至 O(n)
  • 空间复杂度O(n)
缺陷
  • 无效元素积累:堆中可能保留大量已离开窗口的元素,导致堆操作效率降低。

在此之上,我们延续优先队列的思路,对代码进行一下优化

优化方案1:单调队列(双端队列)

使用双端队列(Deque)维护一个严格递减的序列,队首始终是当前窗口最大值。时间复杂度优化至 O(n)

import java.util.Deque;
import java.util.LinkedList;public class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 0) return new int[0];Deque<Integer> deque = new LinkedList<>(); // 存储索引int[] result = new int[nums.length - k + 1];for (int i = 0; i < nums.length; i++) {// 1. 清理超出窗口的队首元素while (!deque.isEmpty() && deque.peekFirst() < i - k + 1) {deque.pollFirst();}// 2. 从队尾移除小于当前元素的索引while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {deque.pollLast();}deque.offerLast(i); // 3. 当前索引入队// 4. 记录窗口最大值(从第k-1个元素开始)if (i >= k - 1) {result[i - k + 1] = nums[deque.peekFirst()];}}return result;}
}

核心改进
  1. 严格递减队列: 每次添加新元素时,从队尾移除所有小于它的元素索引,确保队列严格递减。
  2. 队首即最大值: 队首对应元素始终为当前窗口最大值。
  3. 即时清理无效元素: 在添加新元素前,先清理离开窗口的队首元素,避免无效积累。
复杂度分析
  • 时间复杂度O(n) 每个元素最多入队和出队一次。
  • 空间复杂度O(k) 队列最多存储 k 个元素。
优化方案2:分块预处理(空间换时间)

将数组分成大小为 k 的块,预处理每个块的 前缀最大值后缀最大值,利用二者快速计算窗口最大值。

public class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 0) return new int[0];int n = nums.length;int[] prefixMax = new int[n];int[] suffixMax = new int[n];// 计算前缀最大值for (int i = 0; i < n; i++) {prefixMax[i] = (i % k == 0) ? nums[i] : Math.max(prefixMax[i - 1], nums[i]);}// 计算后缀最大值suffixMax[n - 1] = nums[n - 1];for (int i = n - 2; i >= 0; i--) {suffixMax[i] = ((i + 1) % k == 0) ? nums[i] : Math.max(suffixMax[i + 1], nums[i]);}// 计算每个窗口最大值int[] result = new int[n - k + 1];for (int i = 0; i <= n - k; i++) {result[i] = Math.max(suffixMax[i], prefixMax[i + k - 1]);}return result;}
}

核心逻辑
  1. 前缀最大值: prefixMax[i] = 从块起点到 i 的最大值。
  2. 后缀最大值: suffixMax[i] = 从 i 到块终点的最大值。
  3. 窗口最大值: 设窗口为 [i, j]j = i + k - 1),则最大值 = max(suffixMax[i], prefixMax[j])
复杂度分析
  • 时间复杂度O(n) 预处理和计算结果各需遍历一次数组。
  • 空间复杂度O(n) 需额外存储前缀和后缀最大值数组。
总结
方法时间复杂度空间复杂度核心优势
优先队列(修正)O(n log n)O(n)逻辑简单,易实现
单调队列O(n)O(k)最优效率,推荐使用
分块预处理O(n)O(n)无队列操作,适合并行计算

推荐实现单调队列法在性能和代码简洁性上达到最佳平衡,是解决滑动窗口最大值问题的首选方案。

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

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

相关文章

“互联网 +”时代下开源 AI 大模型 AI 智能名片 S2B2C 商城小程序:行业变革与未来展望

摘要&#xff1a;在“互联网 ”浪潮的推动下&#xff0c;各行业正经历着深度融合与变革。互联网、新零售、云计算等新兴技术成为行业发展的关键驱动力。本文聚焦开源 AI 大模型 AI 智能名片 S2B2C 商城小程序这一创新模式&#xff0c;分析其在“互联网 ”背景下的内涵与优势&am…

ROS2通信机制实战——从“单向传数据”到“双向发请求”(二)

第2天&#xff1a;ROS2通信机制实战——从“单向传数据”到“双向发请求” 做机器人开发时&#xff1a;“为什么控制机器人前进用话题&#xff0c;而让机器人报位置要用服务&#xff1f;”其实答案很简单——ROS2的通信机制是“按需设计”的&#xff1a;话题适合高频、单向的数…

Function Calling(智能客服)

目录 1.0.思路分析 1.1.基础CRUD 1.1.1.数据库表 1.1.2.引入依赖 1.1.3.配置数据库 1.1.4.基础代码 2.定义Function 2.1.课程表的字段&#xff1a; 2.2.定义Function 2.3.System提示词 2.4.配置ChatClient 3.编写Controller 3.1.解决兼容性问题 3.2.AlibabaOpenA…

探索淀粉深加工的无限可能:2026 济南展览会前瞻

在全球农产品加工的广阔版图中&#xff0c;淀粉深加工产业犹如一颗璀璨的明珠&#xff0c;散发着日益耀眼的光芒。其产品广泛渗透于食品、饮料、医药、化工、能源等诸多领域&#xff0c;宛如一条条无形的纽带&#xff0c;将各个行业紧密相连。随着技术的日新月异、政策的大力扶…

STAGEWISE实战指南:从集成到使用的完整解决方案

文章目录 一、前言 二、集成STAGEWISE的实战过程 1. 初始配置问题 2. 依赖冲突处理 3. 组件导入问题 四、标准集成方案 1. 完整安装步骤 2. Vue项目集成步骤 (1) 修改App.vue文件 (2) 配置文件说明 五、最佳实践 1. 开发规范 2. 常见问题排查 五、总结 一、前言 在前端开发中,…

使用astah制作专业状态图及C/C++实现解析

<摘要> 本文详细解析如何使用astah专业工具绘制高质量的UML状态图&#xff0c;并建立与C/C代码的完整映射关系。内容涵盖状态图核心概念、astah工具实操指南、触发机制(Trigger)、守卫条件(Guard)和动作(Action)的代码实现解析&#xff0c;并通过一个完整的用户登录状态机…

C语言————函数递归(通俗易懂)

我们在学习些新的函数时&#xff0c;首先我们得理解它是什么&#xff1f;是怎么定义的&#xff1f;然后去了解他的用途&#xff0c;最后我们自己要会用&#xff0c;知道用在什么地方&#xff1f;什么时候用&#xff1f;用的时候要注意些什么&#xff1f;有一个条理清晰的学习逻…

路由基础(三):静态路由、动态路由、默认路由

静态路由 静态路由&#xff1a;管理员使用手工方式为路由器添加路由 三种添加静态路由的方式&#xff1a; 配置下一跳配置出接口出接口和下一跳都配置 备注&#xff1a;不配置出接口时&#xff0c;路由器会进行路由递归查询 #添加去往10.1.1.0网段的静态路由&#xff0c;下一跳…

大模型开发之:LangChain4j【附资料】

什么是 LangChain4j&#xff1f; LangChain4j 是一个专为 Java 生态系统设计的开源&#xff08;Apache 2.0 许可&#xff09;框架&#xff0c;用于简化基于大语言模型&#xff08;LLM&#xff09;的应用程序开发。它的名字和灵感来源于其"前辈"——为 Python 设计的 …

SyntaxError: Failed to execute ‘open‘ on ‘XMLHttpRequest‘: Invalid URL

这就是在ajax请求的时候URL不正确&#xff0c; 例如&#xff1a; http://192.168.124.168:8082api/v1/task/get 正确的是这样的&#xff1a; http://192.168.124.168:8082/api/v1/task/get 这个错误的来源是 baseUrl apiUrl 导致的&#xff0c; 比如baseUrl http://19…

程序代码篇---类

为什么有类&#xff1a;要理解编程语言中为什么会有 “类”&#xff0c;我们可以从日常生活的例子入手。想象你要描述 “汽车” 这个事物&#xff1a;它有属性&#xff08;颜色、品牌、排量&#xff09;它有行为&#xff08;行驶、刹车、鸣笛&#xff09;如果没有类&#xff0c…

jenkins备份迁移

1、确认Jenkins版本 在web界面操作步骤&#xff1a;登录Jenkins管理控制台点击左上角"Jenkins"图标选择"Manage Jenkins" > "About Jenkins"在页面中查看"Version"字段显示的具体版本号&#xff08;如2.479.2&#xff09; 建议截图…

Video Ocean 接入 GPT-5

Video Ocean&#xff1a;全球首个接入 GPT-5 的视频智能体引领 AI 视频创作革命 一、技术全景&#xff1a;Video Ocean 的架构与创新 1.1 全球首个 GPT-5 视频智能体的技术突破 Video Ocean 作为全球首个接入 GPT-5 的视频智能体&#xff0c;代表了 AI 视频生成领域的重大突…

如何在API高并发中玩转资源隔离与限流策略?

url: /posts/4ad4ec1dbd80bcf5670fb397ca7cc68c/ title: 如何在API高并发中玩转资源隔离与限流策略? date: 2025-08-27T23:26:45+08:00 lastmod: 2025-08-27T23:26:45+08:00 author: cmdragon summary: 资源隔离是保障API稳定性的核心,通过路由隔离和依赖隔离实现关键业务与…

Swift 解法详解 LeetCode 365:水壶问题

文章目录摘要描述题解答案题解代码分析代码拆解示例测试及结果时间复杂度空间复杂度总结摘要 这道题其实就是经典的 “两个水壶问题”&#xff0c;你可能在电影《虎胆龙威3》里见过&#xff0c;布鲁斯威利斯用两个水壶精确量出 4 升水来解除炸弹。这题就是把那个场景搬到了编程…

Redis集群介绍——主从、哨兵、集群

Redis集群介绍 集群里有三大模式&#xff1a; Redis主从模式&#xff1a;一主一从或一主多从&#xff0c;自带读写分离&#xff0c;负载均衡&#xff1b; Redis哨兵模式&#xff1a;高可用&#xff0c;主服务器宕机&#xff0c;从服务器变为主服务器&#xff1b; Redis集群…

【大前端】封装一个React Native与Android/IOS 端通用的埋点接口

RN 层只暴露一个统一的埋点方法&#xff0c;例如 trackEvent(eventName, params)&#xff0c;内部通过 NativeModule 调用 Android/iOS 的原生埋点 SDK。这样 RN 层不用关心具体实现。写一个通用的示例&#xff1a;1. RN 层封装统一接口&#xff08;JS 代码&#xff09;// anal…

详解 外部负载均衡器 → Ingress Controller Pod 这个过程

在常见的生产架构中&#xff1a; 外部负载均衡器&#xff08;Ng/ELB/ALB/NLB等&#xff09;终止来自客户端的 HTTPS 连接。 它将解密后的明文 HTTP 请求转发给后端的 Kubernetes Ingress Controller Pods。 Ingress Controller 处理 HTTP 请求&#xff0c;并将 HTTP 响应返回给…

Markdown 编辑器 语法

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

【PyTorch项目实战】SAM(Segment Anything Model) —— 致力于建立第一个图像分割基础模型

文章目录一、SAM&#xff08;Segment Anything Model&#xff09; —— 致力于建立第一个图像分割基础模型&#xff08;Foundation Model&#xff09;1、项目背景2、核心任务设计3、模型架构&#xff1a;图像编码器 提示编码器 掩码解码器4、核心创新&#xff1a;可提示分割任…