滑动窗口算法精解:用C++高效解决子串/子数组问题
创作时间:
作者:
@小白创作中心
滑动窗口算法精解:用C++高效解决子串/子数组问题
引用
CSDN
1.
https://m.blog.csdn.net/muzibuku/article/details/146169125
滑动窗口算法是一种高效处理连续子序列问题的算法,通过维护一个动态变化的窗口区间,将暴力算法的O(n²)时间复杂度优化到O(n)。本文将从滑动窗口算法的基本概念出发,通过多个经典应用场景的代码实现,深入解析其核心思想和适用场景。
一、滑动窗口的本质:智能伸缩的取景框
滑动窗口算法如同一个智能摄像机,在数据序列中寻找最完美的"镜头"。它通过维护一个动态变化的窗口区间,将暴力算法的O(n²)时间复杂度优化到O(n),特别适用于解决连续子序列相关问题。我们将从三大经典应用场景深入解析:
二、滑动窗口的三大核心要素
2.1 窗口维护三要素
int slidingWindowTemplate(vector<int>& nums, int k) {
int left = 0, right = 0; // 双指针定义窗口边界
unordered_map<int, int> window; // 窗口状态记录
int valid = 0; // 满足条件的指标
while (right < nums.size()) {
// 1. 扩展右边界
int c = nums[right++];
window[c]++;
if (window[c] == k) valid++;
// 2. 收缩左边界条件
while (valid == target) {
// 3. 更新最优解
res = min(res, right - left);
int d = nums[left++];
if (window[d] == k) valid--;
window[d]--;
}
}
return res;
}
2.2 算法复杂度分析
问题类型 | 暴力复杂度 | 滑动窗口复杂度 | 优化倍数 |
|---|---|---|---|
最长无重复子串 | O(n²) | O(n) | n倍 |
最小覆盖子串 | O(n²) | O(n+m) | n/m倍 |
长度最小子数组 | O(n²) | O(n) | n倍 |
三、基础应用:最长无重复子串(LeetCode 3)
3.1 哈希表+双指针实现
int lengthOfLongestSubstring(string s) {
vector<int> map(128, -1); // ASCII直接寻址
int maxLen = 0, left = 0;
for (int right = 0; right < s.size(); ++right) {
if (map[s[right]] >= left)
left = map[s[right]] + 1; // 跳跃收缩
map[s[right]] = right; // 记录最新位置
maxLen = max(maxLen, right - left + 1);
}
return maxLen;
}
// 输入:"abcabcbb" → 输出:3("abc")
算法亮点:
- ASCII直接映射:O(1)时间查询
- 左边界跳跃:避免逐次收缩
- 实时更新最大值:无需额外存储
四、进阶应用:最小覆盖子串(LeetCode 76)
4.1 多条件窗口维护
string minWindow(string s, string t) {
unordered_map<char, int> need, window;
for (char c : t) need[c]++;
int left = 0, right = 0;
int valid = 0, start = 0, len = INT_MAX;
while (right < s.size()) {
char c = s[right++];
if (need.count(c)) {
window[c]++;
if (window[c] == need[c]) valid++;
}
while (valid == need.size()) {
if (right - left < len) {
start = left;
len = right - left;
}
char d = s[left++];
if (need.count(d)) {
if (window[d] == need[d]) valid--;
window[d]--;
}
}
}
return len == INT_MAX ? "" : s.substr(start, len);
}
// 输入:s = "ADOBECODEBANC", t = "ABC" → 输出:"BANC"
关键技巧:
- 需求字典(need):记录目标字符频次
- 有效计数(valid):跟踪匹配字符数
- 动态记录最优解:实时更新最小窗口
五、滑动窗口的四大变种
5.1 固定窗口大小
vector<double> findAverages(vector<int>& arr, int k) {
vector<double> res;
int sum = 0;
for (int right = 0; right < arr.size(); ++right) {
sum += arr[right];
if (right >= k-1) {
res.push_back(sum / (double)k);
sum -= arr[right - k + 1];
}
}
return res;
}
// 输入:[1,3,2,6,-1], k=3 → 输出:[2.0, 3.67, 2.33]
5.2 最多K次替换后的最长子串
int characterReplacement(string s, int k) {
vector<int> count(26);
int maxCount = 0, maxLen = 0;
int left = 0;
for (int right = 0; right < s.size(); ++right) {
maxCount = max(maxCount, ++count[s[right]-'A']);
while (right-left+1 - maxCount > k) {
count[s[left++]-'A']--;
}
maxLen = max(maxLen, right-left+1);
}
return maxLen;
}
// 输入:s="AABABBA", k=1 → 输出:4("AABA"→"AAAA")
六、性能优化与陷阱规避
6.1 常见性能陷阱
陷阱类型 | 错误示例 | 优化方案 |
|---|---|---|
无效窗口收缩 | 每次移动左边界1位 | 跳跃收缩 |
冗余状态计算 | 每次重新统计窗口内容 | 增量更新 |
哈希表查询瓶颈 | 频繁使用count()检查 | 数组直接寻址 |
指针更新顺序错误 | 先移动指针再更新状态 | 先处理当前状态再移动 |
6.2 高级优化技巧
// 优化点1:数组替代哈希表
vector<int> count(128, 0); // 处理ASCII字符
// 优化点2:跳跃收缩左边界
left = max(left, lastPos + 1);
// 优化点3:提前终止循环
if (maxLen == s.size()) break;
七、滑动窗口的六大应用场景
- 子串搜索:最小覆盖子串、字母异位词
- 数组统计:最大平均值、乘积小于K
- 流式处理:数据流中位数、最近K元素
- 字符串分析:重复DNA序列、回文子串
- 时间序列:股票最佳时机、日程安排
- 资源分配:课程安排、任务调度
结语:滑动窗口的智慧之光
滑动窗口算法展现了算法设计的三个核心哲学:
- 时空权衡:用空间记录状态换取时间效率
- 增量思维:避免重复计算已有信息
- 最优剪枝:及时排除无效解可能
当你在LeetCode遇到以下题目时,滑动窗口将是你的破题利器:
- 长度最小的子数组
- 替换后的最长重复字符
- 字符串的排列
掌握滑动窗口的精髓,你将能优雅地解决大量子序列问题,如同拥有解开数据迷宫的万能钥匙。记住:优秀的算法不是魔法,而是对问题模式的深刻洞察与巧妙建模。
热门推荐
牛奶的营养与健康价值
如何调整数字人的语速
如何利用日本国会图书馆的远程复印获得心仪的绝版资料(2024新版本)
《滤镜》:苏渺之死,撕开当代青年的容貌焦虑与身份困局!
被诈骗怎么办?证据的收集与法律应对指南
推荐10部爆笑公路喜剧电影,笑点密集,根本停不下来!
10部爆笑公路喜剧电影推荐:从美国到德国,笑点密集停不下来!
中国高铁时速从350公里提升至400公里,意味着什么?
红外线理疗灯的使用指南:作用、禁忌症及注意事项全解析
颈椎不稳最有效的锻炼方法
四物汤适合什么样的女性喝
总计13万吨,2024年,解放军海军,到底下水了哪些舰艇?
奥美拉唑能和健胃消食片一起吃吗
血糖高的人适合吃甜玉米还是糯玉米?
刷短视频停不下来,该如何应对?
天才少年曾凡博:能够冲击NBA的中国少年,中国篮球的希望
成人用药量和孩子用量比例 老年儿童用药剂量如何折算
好玩的二次元网络游戏有哪些 趣味二次元手游盘点2024
从一双鞋看中国皮鞋发展史
合理选择不同采血方法
被猫咬伤后怎么办?专业处理方法与注意事项
同理心一旦泛滥,离崩溃也就不远了
5吨随车吊:参数、配置与选购指南
女性突然腰疼:警惕这六大疾病,及时就医是关键
新产品如何验证市场需求
徽式建筑:独特的结构与文化内涵
中国汽车再获认可 比亚迪李柯得2025年全球汽车年度人物桂冠
改善足弓受力可以瘦腿吗
冬季小个子女生显高显瘦穿搭指南:短款外套、高腰设计、层次搭配一应俱全
显卡显存揭秘:增加显存就能提升游戏性能吗?