滑动窗口算法概述
滑动窗口是一种利用双指针维护动态区间的高效技巧。通过移动左右指针扩大或收缩窗口,我们可以在一次遍历中完成计算,时间复杂度通常优化至 O(n)。
典型应用场景:
- 寻找最长无重复字符的子串
- 找到和为目标值的最短子数组
- 字符串的排列匹配
核心逻辑:
- 定义
left和right指针,初始指向首元素。 right向右移动进窗口,更新当前状态(如求和、计数)。- 当窗口不满足条件时,
left向右移动出窗口,直到满足要求。 - 在合法状态下更新结果。
- 结束条件是
right越界。
下面结合具体题目展开分析,看看如何灵活应用这一模板。
题目一:长度最小的子数组
问题背景
给定一个含有 n 个正整数的数组和一个正整数 target,找出该数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
解题思路
由于数组元素均为正整数,累加和具有单调性,非常适合套用滑动窗口模板。
- 初始化:
left和right指向首元素,sum记录当前窗口和,len记录最小长度(初始化为最大值)。 - 扩展窗口:
right向右移动,将元素加入sum。 - 收缩窗口:当
sum >= target时,说明当前窗口满足条件。此时尝试缩小窗口以寻找更优解:更新len,然后left右移并减去对应元素,直到sum < target。
注意:在收缩窗口的过程中,只要
sum >= target,都要尝试更新结果,因为可能存在更短的合法子数组。
代码实现
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0, right = 0;
int len = INT_MAX, sum = 0;
while(right < nums.size()) {
sum += nums[right]; // 进窗口,累加
while(sum >= target) {
len = (len, right - left + );
sum -= nums[left++];
}
right++;
}
len == INT_MAX ? : len;
}
};


