能用滑动窗口解决的题目,通常有个前提:数组元素都是正整数。这样当窗口向右扩张时,总和单调递增;收缩时则单调递减。这种单调性是我们判断何时移动左指针的关键。
以 LeetCode 209 题'长度最小的子数组'为例,我们需要找到和大于等于 target 的最短连续子数组。
思路其实很直观:维护一个窗口 [left, right],不断右移 right 扩大范围,一旦窗口内和满足条件,就尝试右移 left 缩小范围,同时记录最小长度。
下面直接看 Python 实现。注意变量初始化和边界情况,比如最后没有满足条件的子数组要返回 0。
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
n = len(nums)
# 初始化答案为比最大可能长度还大,方便后续取最小值
ans = n + 1
s = left = 0
for right, x in enumerate(nums):
# 扩展右边界,累加当前元素
s += x
# 当窗口和满足条件时,尝试收缩左边界
while s >= target:
ans = min(ans, right - left + 1)
s -= nums[left]
left += 1
# 如果 ans 没变过,说明没有找到符合条件的子数组
return ans if ans != n + 1 else 0
时间复杂度是 O(n),因为每个元素最多被加入和移除一次。空间复杂度 O(1)。实际写的时候要注意列表索引不要越界,虽然这里逻辑保证了不会越界。


