1. 不定长滑动窗口算法概述
滑动窗口算法是解决数组/字符串子区间问题的一把利器,尤其适合处理"连续子数组"类问题。不定长滑动窗口作为其中重要分支,其核心思想是通过动态调整窗口边界来寻找满足特定条件的最优解。
1.1 基本概念与适用场景
不定长滑动窗口与定长滑动窗口的主要区别在于窗口尺寸会随着条件变化而动态调整。它通常用于解决以下三类问题:
- 求最长子数组:在满足特定条件下寻找最长的连续子序列(如无重复字符的最长子串)
- 求最短子数组:寻找满足条件的最短连续子序列(如和≥target的最短子数组)
- 求子数组个数:统计满足特定条件的子数组数量
这类问题的共同特征是:当窗口扩大时,可能违反条件;窗口缩小时,可能满足条件。这种"单调性"使得滑动窗口算法成为最优解。
1.2 算法框架与核心要素
不定长滑动窗口的标准框架包含三个关键操作:
- 右指针移动(入队):扩展窗口,纳入新元素
- 左指针移动(出队):收缩窗口,排除元素
- 条件检查与结果更新:在每次窗口调整后验证条件并记录最优解
cpp复制int slidingWindow(vector<int>& nums) {
int left = 0, ans = 0;
for(int right = 0; right < nums.size(); right++) {
// 1. 将nums[right]加入窗口
// 2. while(窗口不符合条件) 移动left缩小窗口
// 3. 更新答案
}
return ans;
}
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 最长子数组问题解析
2.1 无重复字符的最长子串
这是滑动窗口的经典应用,要求找到不含重复字符的最长连续子串。
解题思路:
- 使用哈希表记录字符最后出现的位置
- 当遇到重复字符时,快速跳转左指针
- 始终保持窗口内字符唯一
cpp复制class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> lastPos;
int ans = 0, left = 0;
for(int right = 0; right < s.size(); right++) {
if(lastPos.count(s[right])) {
left = max(left, lastPos[s[right]] + 1);
}
lastPos[s[right]] = right;
ans = max(ans, right - left + 1);
}
return ans;
}
};
复杂度分析:
- 时间复杂度:O(n),每个字符最多被访问两次
- 空间复杂度:O(min(m,n)),m为字符集大小
关键点:当发现重复字符时,left直接跳到该字符上次出现位置的下一位,避免不必要的逐步移动。
2.2 最多K次重复的最长子串
这是上一题的变种,允许每个字符最多出现k次。
cpp复制class Solution {
public:
int maxKRepeatingSubstring(string s, int k) {
unorde
