LeetCode第239题:滑动窗口k内求最大值

devtools/2024/10/23 22:59:41/

来源:LeetCode第239题
难度:困难

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
这段代码实现了 滑动窗口最大值 的问题,使用了 双端队列(deque)来高效地找到数组 nums 中每个大小为 k 的滑动窗口的最大值。以下是代码的详细解析:

代码概述

public int[] maxSlidingWindow(int[] nums, int k) {int index = 0, len = nums.length;int[] ans = new int[len - k + 1];// 双端队列,存储元素的下标Deque<Integer> deque = new ArrayDeque<>();for (int i = 0; i < len; i++) {// 如果队列中队头元素和当前元素位置相差i-k,相当于队头元素要出窗口了,就把队头元素给移除。if (!deque.isEmpty() && deque.peekFirst() <= i - k)deque.pollFirst();// 在添加一个值之前,前面比他小的都要被移除掉,并且还要保证窗口中队列头部元素永远是队列中最大的。while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i])deque.pollLast();deque.addLast(i); // 当前元素的下标加入到队列的尾部。// 当窗口的长度大于等于k个的时候才开始计算(注意这里的i是从0开始的)。if (i >= k - 1)// 队头元素是队列中最大的,把队列头部的元素加入到数组中。ans[index++] = nums[deque.peekFirst()];}return ans;
}

详细解析

初始化:

int index = 0: 用于跟踪结果数组 ans 中下一个最大值要存储的位置。
int len = nums.length: nums 数组的长度。
int[] ans = new int[len - k + 1]: 结果数组,用于存储每个滑动窗口的最大值。大小为 len - k + 1,因为数组中有这么多大小为 k 的窗口。
Deque deque = new ArrayDeque<>(): 创建一个双端队列,用于存储数组元素的下标。
遍历数组:

for (int i = 0; i < len; i++): 遍历每一个元素。
移除超出窗口的下标:

if (!deque.isEmpty() && deque.peekFirst() <= i - k): 检查队列的队头(最大值的下标)是否超出了当前窗口的范围。如果超出,移除队头元素。
维护队列中的最大值:

while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]): 当当前元素 nums[i] 大于队列中对应的元素时,移除队列末尾的下标。这确保队列中的下标对应的元素是当前窗口中的潜在最大值。
deque.addLast(i): 将当前元素的下标 i 加入到队列的末尾。
记录最大值:

if (i >= k - 1): 判断当前索引 i 是否到达第一个有效窗口的结束(即 i 至少为 k - 1)。
ans[index++] = nums[deque.peekFirst()]: 将队列头部的元素(即当前窗口的最大值)存储到结果数组 ans 中。
返回结果:

return ans;: 返回包含每个滑动窗口最大值的数组。
时间复杂度
算法的时间复杂度为 O(n),其中 n 是 nums 数组的元素数量。每个元素最多被加入和移除队列一次,使得算法在处理大输入时非常高效。
空间复杂度
空间复杂度为 O(k),因为在最坏情况下,队列最多可以存储 k 个下标。
示例
假设 nums = [1, 3, -1, -3, 5, 3, 6, 7] 且 k = 3:

滑动窗口的最大值如下:
窗口 1: [1, 3, -1] -> 最大值 = 3
窗口 2: [3, -1, -3] -> 最大值 = 3
窗口 3: [-1, -3, 5] -> 最大值 = 5
窗口 4: [-3, 5, 3] -> 最大值 = 5
窗口 5: [5, 3, 6] -> 最大值 = 6
窗口 6: [3, 6, 7] -> 最大值 = 7
最终的输出将是 [3, 3, 5, 5, 6, 7]。

这种方法既高效又清晰,利用双端队列有效地维护滑动窗口中的最大值。


http://www.ppmy.cn/devtools/128284.html

相关文章

c++查看运行时类型

c查看运行时类型方法有三&#xff1a; visual studio的监视 c98查看运行时类型 #include <typeinfo> #include <iostream> using namespace std; int main() {int i 0;cout << typeid(i).name() << endl;//intcout << (typeid(i) typeid(int…

力扣71~75题

题71&#xff08;中等&#xff09;&#xff1a; python代码&#xff1a; class Solution:def simplifyPath(self, path: str) -> str:#首先根据/分割字符串&#xff0c;再使用栈来遍历存储p_listpath.split(/)p_stack[]for i in p_list:#如果为空则肯定是//或者///if i:con…

计算机网络自顶向下(3)---TCPsocket

1.TCPsocket TCPsocket是指使用传输控制协议&#xff08;TCP&#xff09;的网络套接字。套接字是网络中两台计算机之间进行通信的端点。TCP是一种可靠的、面向连接的协议&#xff0c;提供了错误检测、流量控制和拥塞控制等功能。 TCPsocket通常用于客户端-服务器通信&#xff0…

【软件测试】理论杂记 + Selenium

文章目录 测试用例万能公式基于测试对象黑盒测试方法 白盒测试Selenium选择器CSS选择器XPath选择器 等待常用API浏览器操作 测试用例万能公式 功能&#xff0c;界面&#xff0c;易用&#xff0c;兼容&#xff0c;安全&#xff0c;性能&#xff0c;网络 基于测试对象 界面测试…

Greiner 经典力学(多体系统和哈密顿力学) 第十章 学习笔记

第十章 学习笔记 &#xff08;The Virbrating Membrane&#xff09; 这一章研究的是一个薄膜的振动问题。基本假设条件与上一章类似。 首先是振动幅度很小。 薄膜的张力 T 认为是恒定的。 类似弦振动问题推导&#xff0c;将其推广到二维平面上&#xff0c;就可以得到膜的振…

RAPIDS cuDF pandas

使用 RAPIDS cuDF pandas 加速器模式处理 10 亿行数据 文章目录 前言一、使用 RAPIDS cuDF pandas 加速器模式进行数据处理二、RAPIDS cuDF pandas 加速器模式下的新大型数据处理功能 24.081. 大字符串支持2. 带预提取的托管内存池三、使用 NVIDIA GPU 运行一亿行挑战赛1. NVID…

用Java爬虫API,轻松获取电商商品SKU信息

在电子商务的精细化运营时代&#xff0c;SKU信息的重要性不言而喻。SKU&#xff08;Stock Keeping Unit&#xff09;信息不仅包含了商品的规格、价格、库存等关键数据&#xff0c;还直接影响到库存管理、价格策略和市场分析等多个方面。如何高效、准确地获取这些信息&#xff0…

万能接口PCIE

一、PCIE插槽的崛起 随着计算机技术的飞速发展&#xff0c;主板上的扩展插槽也在不断演进。PCIE插槽&#xff0c;作为新一代的高速串行扩展总线标准&#xff0c;已经逐渐取代了早期的PCI和AGP插槽&#xff0c;成为现代主板上的主流扩展接口。 二、PCIE插槽的特性 高速串行传…