双指针的变体:滑动窗口与长度最小的子数组问题

简介: 滑动窗口是一种高效的双指针技巧,常用于解决数组或字符串中的连续子区间问题。通过维护一个由 left 和 right 指针界定的窗口,动态调整其大小,以寻找满足特定条件的最优解。它常用于求解连续子数组的最值、字符子串判断等,如“长度最小的子数组”、“水果采摘”、“最小覆盖子串”等问题。核心思想是:在满足条件时收缩窗口,在不满足时扩展窗口,结合哈希表等结构维护窗口内状态,从而实现线性时间复杂度 O(n) 的高效求解。掌握滑动窗口的关键在于理解其模板结构,并灵活应对不同题目的状态维护需求。

今天复习了“长度最小的子数组”这道题,突然对滑动窗口这个技巧有了更深的理解。滑动窗口其实是双指针的一种变体,它用两个指针(一般叫 left 和 right)维护一个区间(也可以理解为一个“窗口”),根据题目的不同需求,动态地调整窗口的左右边界。

有趣的是,虽然代码里可能用了两个循环,但滑动窗口的时间复杂度依然是 O(n)。这是因为每个元素最多被“看”两次:一次被 right 扫进去窗口,一次被 left 从窗口移出去。因此整体上仍然是线性时间。

什么时候使用滑动窗口?
滑动窗口特别适合在一个连续区间内寻找某种性质的问题,比如:
连续子数组的最大/最小长度
连续子串是否包含某些字符
一段区间内最多/最少包含多少种元素
你可以把它想象成一扇在数组上移动的窗户,这扇窗户只关心“窗户里的内容”是否满足某种条件。一旦满足,就尝试收缩窗户(优化结果);不满足,就扩展窗户(继续寻找)。

滑动窗口的基本用法
滑动窗口的核心步骤其实很固定,基本可以套模板:
初始化窗口的两个边界:left 和 right
不断移动右边界 right,扩大窗口,直到满足条件
当条件满足后,尝试移动左边界 left,缩小窗口,同时记录最优结果
重复上述过程,直到右边界走到尽头

例题分析一:长度最小的子数组
这道题是滑动窗口的经典题型:
给你一个整数数组 nums 和一个整数目标值 target,请你找出数组中 总和 大于等于 target 的 最短子数组 的长度,并返回该长度。如果不存在符合条件的子数组,返回 0。
这个题目的关键点是:子数组必须是连续的,并且我们要在所有满足条件的子数组中找到最短的一个。
所以思路就是:

移动右指针,不断累加窗口内的和

一旦窗口内的和 ≥ target,就尝试移动左指针缩小窗口

每次满足条件时,更新最小长度

虽然是两个指针嵌套循环,但每个指针只会走一遍数组,所以时间复杂度仍是 O(n)。

例题分析二:Total Fruit(最多采几棵树的水果)
这题和长度最小子数组很像,也是滑动窗口。不同的是这题需要统计种类数量,而不是数值总和。
在 Python 中可以用 Counter() 或字典来维护窗口内每种水果的数量。
每次移动右指针采一棵水果,同时把它记录进字典。如果种类超过两种,就移动左指针,并更新字典(数量减1,为0就 pop 掉)。最终记录窗口的最大长度就是答案。

例题分析三:最小覆盖子串(minWindow)
这道题是滑动窗口中难度稍高的一道,很多人(包括我)第一次做都卡在了字典的使用上。
题目要求:
给两个字符串 s 和 t,返回 s 中最短的包含所有 t 中字符的子串(包括重复的字符)。
关键点是:我们不仅要知道有没有这个字符,还要知道每个字符的数量是否足够,因此用了两个 Counter() —— 一个记录 t 中每个字符需要的数量,一个实时记录窗口中字符的数量。
在滑动窗口的过程中,我们还需要一个额外的变量 start 来记录当前“最短窗口”的起始位置。如果找到更短的覆盖,就更新 start 和 min_len。
这也是我第一次意识到,滑动窗口虽然是模板化的写法,但遇到不同的题,窗口里需要维护的状态可能完全不同(和哈希表配合使用是很常见的变体)。

做题久了我还意识到,如果你对 dict、Counter 这些基本结构不熟,就会很难写出滑动窗口的变种。比如我之前卡在 totalFruit 和 minWindow,就是因为不知道怎么去维护窗口里的状态。

目录
相关文章
|
移动开发 NoSQL Redis
阿里云Redis lua命令支持及相关限制说明
介绍阿里云Redis对lua命令的支持
12922 1
从刷题中抽象出来的二分法思维模型
本文总结了二分法的核心理解与应用技巧,探讨了其适用条件与逻辑构建方法。通过明确单调性与边界性质,帮助读者从“凭感觉写”进阶到“有依据设计”,提升对查找、边界与插入位置等问题的掌控力。
386 1
|
4月前
|
缓存 算法 关系型数据库
【分布式】分布式核心组件——分布式ID生成:雪花算法、号段模式、美团Leaf、百度UidGenerator、时钟回拨解决方案
本文系统梳理分布式ID生成核心知识体系,涵盖设计准则(唯一性、有序性、高性能等)、两大技术路线(雪花算法与号段模式)原理及优劣、主流工业方案(美团Leaf、百度UidGenerator)深度解析、时钟回拨全维度应对策略,并提供选型对比与落地避坑指南,助力高可用分布式系统建设。
|
5月前
|
数据采集 人工智能 监控
AI 应用开发流程
AI应用开发已转向“数据与评估导向”,涵盖五大核心环节:业务定义与场景拆解、数据工程与知识库构建、提示词与Agent逻辑开发、评估与安全护栏建设、持续监控与迭代优化。聚焦实效、可控与进化。(238字)
|
12月前
|
算法
今天的刷题记录:螺旋矩阵、区间和、开发商购买土地
本篇介绍了三个经典算法问题:螺旋矩阵通过控制边界按圈遍历;区间和利用前缀和优化求和;开发商买地则采用二维前缀和思想,枚举最优切割方式。三题均注重优化思路与边界处理。
170 0
|
文字识别 计算机视觉 Python
我用 Python 写了一个自动裁剪答题卡区域的小工具(附代码)
本文分享了一种通过 OpenCV 自动裁剪答题卡中答题区域的方法。核心思路是利用答题区域四周的黑色角块进行定位:先通过自适应阈值增强对比度,再用 `cv2.findContours()` 找轮廓,并计算每个轮廓的“紧凑度”(面积 / 周长)筛选出接近方块的角块。最终根据四个角块的边界矩形裁剪出答题区。代码实现详细,适合初学者参考,同时提供了参数调整建议以适配不同图像条件。
547 10
|
人工智能 自然语言处理 安全
💻 Codex 来了:OpenAI 推出多任务软件工程 AI 代理,开发者工作方式将被重塑?
Codex 是 OpenAI 推出的一款云端智能开发代理,基于优化后的 Codex-1 模型,能够执行从代码编写、Bug 修复到 PR 提交的完整工程任务。通过 ChatGPT 的界面,用户可向 Codex 分配任务,它将在独立沙盒中运行并返回结果。Codex 支持多任务异步处理,遵循项目规范(AGENTS.md),并生成日志与测试报告以确保透明性。作为“AI 参与式开发”的里程碑,Codex 不仅提升效率,还可能重塑开发者角色,使他们从具体编码转向指导 AI 完成任务,推动软件工程进入意图驱动的新时代。
2161 16
|
敏捷开发 人工智能 数据可视化
项目管理中的Scrum是什么?适用于哪些项目?
2分钟了解scrum模型的操作定义和适用场景!
990 4
|
存储 Kubernetes 安全
Docker、Containerd、RunC分别是什么
Docker、Containerd、RunC分别是什么
Docker、Containerd、RunC分别是什么
|
Ubuntu Linux 数据安全/隐私保护
Linux系统使用Docker部署Cloudreve云盘并实现远程访问
Linux系统使用Docker部署Cloudreve云盘并实现远程访问
691 0