图解题库 / 滑动窗口

209. 长度最小的子数组

中等 含交互动画

学完这道你应该能: 说清它为什么用「滑动窗口」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

正整数数组中,求和 ≥ target最短连续子数组长度(没有返回 0)。

nums = [2, 3, 1, 2, 4, 3]
target = 7
输出 = 2 (子数组 [4,3])

思路解析

枚举每个起点终点再求和,n² 甚至 n³。换个思路:用一个窗口,右边扩进新数、和够了就从左边缩,全程只扫一遍。

r 不断右移把数加进窗口;一旦窗口和 ≥ target,就记录长度,并尽量把 l 右移缩短窗口(同时减去左端值),直到和不够再继续扩。

r 扩到 3:r 一路扩到下标 3,窗口 [2,3,1,2] 和 = 8 ≥ 7。记下长度 4,开始缩左。

缩左 · l→1:把左端 2 移出,和降到 6 < 7,缩不动了。当前最短仍是 4,继续右扩。

r 扩到 4:r 扩到 4,窗口 [3,1,2,4] 和 = 10 ≥ 7。又能缩左了。

连缩左 · l→3:连续缩左:去掉 3 后 [1,2,4]=7 记长度 3;再去掉 1 后 [2,4]=6 不够,停。最短已是 3。

r 扩到 5:r 扩到最后,窗口 [2,4,3] 和 = 9 ≥ 7,继续缩左找更短。

缩到最短 · [4,3]:去掉左端 2 后 [4,3]=7 ≥ 7,长度 2!这是全程最短,就是答案。

「连续子数组 + 满足某条件求最长/最短」就用滑动窗口:右扩纳入、违规/达标就动左边。无重复最长子串、最小覆盖子串都是它。

参考代码(Python)

Python
1l, s, best = 0, 0, float(class="cl-str">"inf")
2for r in range(len(nums)):
3    s += nums[r]                      # 右边扩进
4    while s >= target:                # 够了就缩左
5        best = min(best, r - l + 1)
6        s -= nums[l]; l += 1
7return 0 if best == float(class="cl-str">"inf") else best

复杂度分析

  • 时间复杂度:O(n) —— l、r 各走一遍
  • 空间复杂度:O(1) —— 几个变量

套路模板

记住骨架:r 右扩纳入、while 里左缩、缩前/后更新答案。求最短在「达标」时更新、求最长在「违规」前更新,是两类窗口的区别。

Python
1# 「连续子数组/子串 + 求最长/最短」都套
2l = 0
3for r in range(n):
4    加入(nums[r])                     # 右扩
5    while 窗口违规 or 已达标:          # 该缩了
6        更新答案()
7        移出(nums[l]); l += 1         # 左缩

易错点

  • 缩窗口时忘了减去左端值 → ✅ s -= nums[l] 再 l += 1(窗口和必须同步维护)
  • 没找到也返回 inf → ✅ 最后判 inf 返回 0(题目要求无解返回 0)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →76. 最小覆盖子串 ← 返回题库