参考: 《laluladong的算法小抄》
滑动窗口
滑动窗口类问题属于双指针问题的一种, 下面总结了解决滑动窗口问题的一种思路.
应用场景:
- 满足某种情况(计算结果, 出现次数, 同时包含)
- 最短/最长
- 子串/子数组/子序列
大致思路:
- 初始情况下, 左右边界处于数据最左侧, 窗口中没有内容
- 在条件不满足的时候拓宽右侧边界
- 在条件满足的时候收缩左侧边界, 更新最优解
- 时间复杂度为 O(n)
代码框架:
//滑动窗口框架
void slideWindow(string s, string t)
{
unordered_map<char, int> need, window;
for(char c : t) need[c]++;
int left = 0, right = 0;
int valid = 0;
while(right < s.size())
{
//c是将移入窗口的字符
char c = s[right];
//右移窗口
right++;
//进行窗口内数据的一系列更新
//...
/*debug 的输出信息*/
printf("window: [%d, %d]\n", left, right);
//判断左侧窗口是否需要收缩
while(windows needs shrink)
{
//d 是将移出窗口的字符
char d = s[left];
//左移窗口
left++;
//进行窗口内数据的一系列更新
//...
}
}
}
相关练习
713. 乘积小于 K 的子数组
解题步骤:
- 确认滑动窗口的左右边界
left
,right
, 使用pro
记录乘积,ret
记录结果数量. - 在边界范围中移动左右窗口, 并记录可能产生的子数组个数(具体看代码)
- 去除特殊情况, 当k<=1时
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
if(k<=1) return 0;
int left = 0, right = 0;
int pro = 1;
int ret = 0;
while(right < nums.size())
{
pro *= nums[right]; //乘积更新
while(pro >= k)
{
pro /= nums[left];
left++; //当乘积大于k时, 除去左指针指向值
}
//*右指针每次移动, 记录可能产生的子数组个数*
ret += right - left + 1;
right++;
}
return ret;
}
};