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

简介: 滑动窗口是一种高效的双指针技巧,常用于解决数组或字符串中的连续子区间问题。通过维护一个由 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,就是因为不知道怎么去维护窗口里的状态。

目录
相关文章
|
测试技术
读完这篇文章后,才发现Allpairs这款工具,让测试用例变得如此简单
读完这篇文章后,才发现Allpairs这款工具,让测试用例变得如此简单
1176 0
|
存储 Kubernetes API
kubernetes【存储】1. 共享存储pv、pvc、StorageClass使用详解(1)
kubernetes【存储】1. 共享存储pv、pvc、StorageClass使用详解(1)
kubernetes【存储】1. 共享存储pv、pvc、StorageClass使用详解(1)
|
文字识别 计算机视觉 Python
我用 Python 写了一个自动裁剪答题卡区域的小工具(附代码)
本文分享了一种通过 OpenCV 自动裁剪答题卡中答题区域的方法。核心思路是利用答题区域四周的黑色角块进行定位:先通过自适应阈值增强对比度,再用 `cv2.findContours()` 找轮廓,并计算每个轮廓的“紧凑度”(面积 / 周长)筛选出接近方块的角块。最终根据四个角块的边界矩形裁剪出答题区。代码实现详细,适合初学者参考,同时提供了参数调整建议以适配不同图像条件。
630 10
|
3月前
|
人工智能 Java API
2026年阿里云千问大模型全解:Qwen3.7模型矩阵、计费与全链路实操指南
2026年阿里云通义千问(代号Qwen)作为全栈自研国产大模型体系,依托百炼大模型服务平台统一对外提供推理、微调、智能体搭建、私有知识库、应用部署等一站式MaaS能力。整套产品不再是单一对话模型,而是覆盖纯文本、代码、图像、音频、视频、行业垂直领域的完整模型矩阵,2026主力迭代版本为Qwen3.7系列,在超长上下文、自主长周期智能体、多模态统一推理三大维度完成全面升级,深度适配国内中文业务场景,同时兼容国际通用API协议,可无缝对接各类IDE插件、开源智能体框架、企业自研业务系统。本文从模型定位、分层产品能力、四大计费体系、多端实操接入、分场景选型、成本优化、常见故障排查七个维度完整拆解,覆
2535 0
|
6月前
|
运维 数据库 数据安全/隐私保护
【微服务】微服务 vs 单体架构 区别、服务拆分原则、DDD领域驱动设计
本文构建“架构对比→拆分准则→DDD方法论→落地实践→避坑指南”闭环体系,系统剖析单体与微服务的本质差异、演进路径及反模式;详解微服务拆分八大原则与六大禁忌;深度整合DDD战略设计(限界上下文即服务边界)与战术设计(四层架构+聚合建模),提供从0到1的渐进式落地路径与各阶段最佳实践。
|
7月前
|
人工智能 JavaScript Linux
🦞OpenClaw高手进阶指南:OpenClaw全平台部署(阿里云/Win11/Mac/Linux)到自定义Skill开发教程
当你还在重复向AI解释工作流程时,掌握技能(Skill)开发的用户已经实现“一次教学,终身复用”。Anthropic官方发布的Claude Skills构建指南,揭示了AI工具自定义的核心逻辑——技能本质是“固化的工作流程指令包”,能让AI按固定规范处理重复任务,从文档生成、流程自动化到MCP工具增强,覆盖全场景需求。
2499 8
|
数据采集 机器学习/深度学习 编解码
小红书 hi lab开源最强多模态大模型dots.vlm1,性能对标闭源 Gemini 2.5 Pro 和 Seed-VL1.5
小红书 hi lab开源最强多模态大模型dots.vlm1,性能对标闭源 Gemini 2.5 Pro 和 Seed-VL1.5
1104 0
小红书 hi lab开源最强多模态大模型dots.vlm1,性能对标闭源 Gemini 2.5 Pro 和 Seed-VL1.5
|
JavaScript iOS开发 MacOS
怎样从`MacOSX` 上完全卸载`Nodejs` ?
MacOS , Nodejs, Homebrew, nvm
4161 0
|
Python
如何使用正则表达式提取网页中的特定信息
如何使用正则表达式提取网页中的特定信息
881 1
|
机器学习/深度学习 人工智能 弹性计算
阿里云PAI-EAS:一键部署通义千问模型的理想平台
随着人工智能技术的飞速发展,大语言模型已经成为了AI领域的研究热点。阿里云研发的通义千问大模型系列,尤其是70亿参数规模的Qwen-7B模型,展示了强大的语言理解和生成能力。然而,对于大多数开发者和企业来说,如何高效部署和应用这样的大模型仍然是一个挑战。幸运的是,阿里云模型在线服务(PAI-EAS)为我们提供了一个一键部署通义千问模型的解决方案。
1520 2

热门文章

最新文章