滑动窗口算法在笔试面试及竞赛中非常常见,主要用于处理数组和字符串问题,特别是涉及连续子数组或子字符串的条件筛选。所谓'滑动窗口',本质上就是维护一段区间,其大小可固定也可变化,通过左右指针的移动来扫描数据结构。基本套路通常包括:扩展右边界、检查条件、更新结果、收缩左边界。
长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target,找出该数组中满足其总和大于等于 target 的长度最小子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例: 输入:target = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
暴力解法需要遍历两次,时间复杂度 O(n^2),对于 n=10^5 的数据规模会超时。虽然前缀和加二分查找能达到 O(n log n),但滑动窗口可以将复杂度优化至 O(n)。
实现思路
我们维护一个滑动窗口,窗口内的值之和小于目标值时扩展右边界,一旦满足条件则尝试收缩左边界以寻找更优解。
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size(), sum = 0, len = INT_MAX;
for (int left = 0, right = 0; right < n; right++) {
sum += nums[right]; // 进窗口
while (sum >= target) {
len = min(len, right - left + 1); // 判断并更新
sum -= nums[left++]; // 出窗口
}
}
return len == INT_MAX ? 0 : len;
}
};
无重复字符的最长子串
给定一个字符串 s,请你找出其中不含有重复字符的最长子串的长度。
示例: 输入:s = "abcabcbb" 输出:3 解释:因为无重复字符的最长子串是 "abc",所以其长度为 3。
这道题同样适用滑动窗口,约束条件变为窗口内不能有重复字符。我们需要借助哈希表(如 unordered_map)来记录字符出现的次数。
实现思路
移动右指针加入字符,若当前字符计数大于 1,说明出现重复,此时移动左指针直到移除重复字符。过程中不断更新最大长度。
class Solution {
public:
int {
unordered_map<, > hash;
n = s.();
len = ;
( i = , j = ; j < n;) {
hash[s[j]] += ;
(hash[s[j]] > ) {
hash[s[i++]]--;
}
len = (len, j - i + );
j++;
}
len == ? : len;
}
};


