news 2026/5/1 6:05:52

双指针专题(九):谁是窗口里的老大?——「滑动窗口最大值」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
双指针专题(九):谁是窗口里的老大?——「滑动窗口最大值」

这道题是LC 239. 滑动窗口最大值(Hard)。 它是所有涉及“区间最值”问题的鼻祖。面试官考这道题,看的就是你能不能在 O(N) 的时间里解决问题,而不是傻傻地用 O(N×K) 去遍历。

场景想象:有一个固定长度为k的窗口在数组上滑动。这就好比一个**“淘汰制的晋升通道”**。

  • 规则 1(能力说话):如果你比前面的老员工(队列里的元素)能力强(数值大),那前面的老员工就废了,永远不可能成为这个窗口里的老大(最大值),直接把他们踢走

  • 规则 2(任期限制):你是这一届最强的(队头),但如果你的任期到了(滑出了窗口范围),你也得退休

力扣 239. 滑动窗口最大值

https://leetcode.cn/problems/sliding-window-maximum/

题目分析:

  • 输入:整数数组nums,窗口大小k

  • 输出:数组,包含每次滑动后的最大值。

例子:nums = [1, 3, -1, -3, 5, 3, 6, 7], k = 3

  1. [1, 3, -1]-> Max: 3

  2. [3, -1, -3]-> Max: 3

  3. [-1, -3, 5]-> Max: 5

  4. ...

核心思维:单调队列 (Monotonic Queue)

我们需要维护一个双端队列 (Deque)。 为了保证队头永远是最大值,这个队列里的元素必须严格单调递减(从大到小)。

队列里存什么?存下标 (index)!而不是存数值。

  • 为什么?因为我们需要通过下标来判断队头元素是否已经**“过期”**(滑出窗口)。如果只存数值,就不知道它什么时候该退休了。

操作三部曲:

  1. 入队(去尾):新元素nums[i]来了。

    • 如果队尾元素 < 新元素:说明队尾是个“又老又弱”的废棋,直接pop踢掉。

    • 重复这个过程,直到队尾元素 >= 新元素,或者队列空了。

    • nums[i]的下标放入队尾。

    • (这一步保证了队列是单调递减的)

  2. 出队(去头)

    • 检查队头下标是否已经小于i - k + 1(即是否滑出了当前窗口)。

    • 如果是,shift踢掉队头。

  3. 记录结果

    • 只要窗口形成(i >= k - 1),队头元素对应的数值就是当前窗口的最大值。

代码实现 (JavaScript)

JavaScript

/** * @param {number[]} nums * @param {number} k * @return {number[]} */ var maxSlidingWindow = function(nums, k) { // 队列存放的是下标 index const queue = []; const result = []; for (let i = 0; i < nums.length; i++) { // 1. 【入队前的清理】:维护单调递减 // 只要队尾元素比当前元素小,就把它踢走 // 因为当前元素更强,而且更晚离开窗口,所以队尾那些“弱者”永远没机会出头了 while (queue.length > 0 && nums[queue[queue.length - 1]] < nums[i]) { queue.pop(); } // 新元素入队 (存下标) queue.push(i); // 2. 【检查队头合法性】:老大多久退休? // 计算窗口左边界:i - k + 1 // 如果队头下标 < i - k + 1,说明它已经滑出去了 if (queue[0] <= i - k) { queue.shift(); // 移除队头 } // 3. 【记录结果】 // 只有当窗口完全形成后(也就是 i 走到 k-1 时),才开始记录 if (i >= k - 1) { // 队头永远是当前窗口的最大值 result.push(nums[queue[0]]); } } return result; };

深度模拟

nums = [1, 3, -1, -3, 5],k = 3

  1. i=0 (值1): 队列[0](对应值1)。

  2. i=1 (值3):

    • 3 比 1 大 -> 弹出 0。

    • 入队 1。队列[1](对应值3)。

  3. i=2 (值-1):

    • -1 比 3 小 -> 保持单调性。

    • 入队 2。队列[1, 2](对应值 3, -1)。

    • 窗口成型:记录最大值nums[1] = 3Res=[3]

  4. i=3 (值-3):

    • -3 比 -1 小 -> 入队 3。队列[1, 2, 3](对应值 3, -1, -3)。

    • 检查队头:队头是 1。当前窗口范围[1, 3]。队头还在,不用退休。

    • 记录最大值nums[1] = 3Res=[3, 3]

  5. i=4 (值5):

    • 5 比 -3 大 -> 弹 3。

    • 5 比 -1 大 -> 弹 2。

    • 5 比 3 大 -> 弹 1。

    • 入队 4。队列[4](对应值 5)。

    • 记录最大值nums[4] = 5Res=[3, 3, 5]

总结

这道题是单调队列的入门即巅峰。 请记住这个“职场法则”:一旦新来的比你强,你就被淘汰了(pop);即使你是最强的,时间到了也得走人(shift)。


下一题预告:K 个不同整数的子数组

这一题(LC 239)解决的是“窗口内的最值”。 下一题LC 992. K 个不同整数的子数组(专项十),我们要解决的是一个极具数学技巧的计数问题。

  • 题目:求有多少个子数组,恰好包含K种不同的整数。

  • 难点:直接求“恰好 K”很难。我们需要把问题转化为“最多 K” - “最多 K-1”。这是一个非常高级的滑动窗口思想。

准备好迎接双指针专题的大结局了吗?

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/26 11:55:08

CSDN官网技术文章排行:HunyuanOCR相关阅读量飙升

HunyuanOCR为何突然爆火&#xff1f;从CSDN阅读量飙升看端到端OCR的落地革命 在智能办公、电子政务和数字金融日益普及的今天&#xff0c;一个看似不起眼的技术环节——光学字符识别&#xff08;OCR&#xff09;&#xff0c;正悄然经历一场深刻变革。过去我们习以为常的“先检测…

作者头像 李华
网站建设 2026/5/1 6:04:43

PyCharm代码提示设置优化HunyuanOCR开发体验

PyCharm代码提示优化提升HunyuanOCR开发效率 在AI应用快速落地的今天&#xff0c;一个高效的本地开发环境往往能决定项目能否在短时间内完成原型验证。尤其是在处理像光学字符识别&#xff08;OCR&#xff09;这样从图像到结构化文本的复杂任务时&#xff0c;开发者不仅需要面对…

作者头像 李华
网站建设 2026/4/28 17:35:10

Markdown编辑器整合OCR?未来文本创作的新范式

视觉即输入&#xff1a;当 OCR 融入 Markdown 编辑&#xff0c;内容创作正在被重新定义 在一次实验室的日常场景中&#xff0c;研究员小李拍下了一张泛黄的手写实验记录纸——字迹潦草、排版混乱。过去&#xff0c;他需要花半小时逐字录入并整理成电子文档&#xff1b;而今天&a…

作者头像 李华
网站建设 2026/4/18 10:42:09

斯坦福大学李飞飞教授团队最新成果,针对具身差异,从零成本视频生成用于交互的3D物体流

Dream2Flow, 简单来说,生成式视频模型能根据文字指令 + 初始图像, “想象” 出人类完成任务的视频(像把面包放进碗), 但机器人看不懂这些人类动作, 没法把视频里的人类操作转化为自己的机械臂 / 关节运动指令, 毕竟机器人不知道怎么动机械臂才能复刻视频里的动作。…

作者头像 李华
网站建设 2026/4/30 4:04:31

飞书文档增强功能:粘贴图片自动提取文字并插入正文

飞书文档增强功能&#xff1a;粘贴图片自动提取文字并插入正文 在日常办公中&#xff0c;你是否曾为一张会议白板照片、一份扫描合同或一段视频字幕而不得不手动逐字录入&#xff1f;这种“看图打字”的操作不仅耗时&#xff0c;还容易出错。更麻烦的是&#xff0c;还要反复切换…

作者头像 李华
网站建设 2026/4/19 14:47:43

火山引擎AI大模型 vs 腾讯混元OCR:谁更适合中文OCR场景?

火山引擎AI大模型 vs 腾讯混元OCR&#xff1a;谁更适合中文OCR场景&#xff1f; 在金融柜台扫描身份证、政务大厅上传申请表、跨境电商处理多语种发票时&#xff0c;我们常遇到一个共性问题&#xff1a;为什么OCR系统总把“张三”识别成“弓长三”&#xff0c;或者漏掉盖章遮挡…

作者头像 李华