滑动窗口算法详解
滑动窗口是处理连续子数组或子串问题的经典技巧。通过维护一个动态区间,利用双指针的单调性,可以将时间复杂度从 O(N²) 优化至 O(N)。本文将结合 C++ 代码,深入剖析核心原理及常见应用场景。
209. 长度最小的子数组
题目描述:给定一个含有 n 个正整数的数组和一个正整数 target,找出该数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度。
思路分析
暴力枚举需要三层循环,效率较低。优化的关键在于利用前缀和的性质:当当前窗口和 sum >= target 时,继续向右扩展右指针只会增加长度,此时应尝试收缩左指针以寻找更短的有效窗口。
代码实现
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.size();
int len = INT_MAX;
int sum = 0;
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;
}
};
注意:虽然使用了嵌套循环结构,但 left 和 right 各自最多移动 N 次,因此总时间复杂度为 O(N)。
3. 无重复字符的最长子串
题目描述:给定一个字符串 s,请你找出其中不含有重复字符的最长子串的长度。
思路分析
我们需要维护一个不包含重复字符的窗口。当右指针遇到重复字符时,左指针必须移动到重复字符上一次出现位置的下一位,以确保窗口内字符唯一。
代码实现
class Solution {
public:
{
hash[] = {};
n = s.();
ret = ;
( left = , right = ; right < n; right++) {
hash[s[right]]++;
(hash[s[right]] > ) {
hash[s[left++]]--;
}
ret = (ret, right - left + );
}
ret;
}
};


