算法刷题之滑动窗口

滑动窗口总结

两种滑动窗口类型:
(1)双指针 + 计数变量(个数,长度~)
(2)双指针 + 哈希表(统计个数,是否出现(重复)~)

(1)对应lc题型:713.乘积小于K的子数组、209.长度最小的子数组、 1004.最大连续1的个数

/*滑动窗口框架*/
int i = 0, j = 0;
int res, sum; //sum, res根据条件(个数,长度等)初始化
while(j < nums.size()) { //窗口变化
	xxx; //统计变量 如sum += nums[i]; sum *= nums[i]; if(nums[i] == ?) ~
	while(xxx) { //窗口缩小条件
		xxx; //缩小窗口前更新结果,如res = min(res, j - i + 1);
		xxx; //如 sum -= nums[i]; sum /= nums[i]; 
		i++; //缩小窗口
	}
	xxxxx; //也可能在这更新结果,如res = max(res, j - i + 1);  res += j - i + 1;
	j++; //增大窗口
}

(2)对应lc(或牛客Top)题型:MD92 最长无重复子数组、3.无重复字符的最长子串、 76.最小覆盖子串 567.字符串的排列、438.找到字符串中所有字母异位词

//一个字符串的情况(string s):经典题:最长无重复子串(子数组)
/*滑动窗口框架1*/
unordered_map<char, int> map; //哈希表根据题意构造,value值通常是个数表示某字符(数)出现多少次、是否出现(重不重复)
int l = 0, r = 0; //维护一个左闭右开的[l,r)窗口
int res; //res记录结果
while(r < s.size()) {
	char c = s[r];
	r++;
	map[c]++;
	while(xxx) { //缩小窗口条件,如map[c] > 1
		char d = s[l];
		l++;
		map[d]--;
	}
	xxx; //结果res更新
}

//两个字符串的情况(string s, string t),窗口更新逻辑较为复杂
/*滑动窗口框架2*/
unordered_map<char, int> window, need;
for(char c : t) need[c]++;

int l = 0, r = 0;
int res, valid = 0; //其中res记录结果(也可能是数组), valid记录合格字符数量
while(r < s.size()) {
	char c = s[r];
	r++;
	xxx; //窗口数据更新
	while(xxx) { //缩小窗口条件,如valid == need.size()
		xxx; //可能在这里更新结果res(或者返回bool值)
		char d = s[l];
		l++;
		xxx; //窗口数据更新
	}
}
注意:

1.结果更新位置不固定,可能在窗口真正缩小前,也可能在其之后(特指内层while后)。

2.内层while循环上下具有一定的相似性(对称性)。

3.哈希表框架的前提是维护了一个左闭右开的区间:窗口。相对哈希表,计数变量框架的窗口增大逻辑往往放在内层while循环之后,数据更新通常在二者之间。

4.此框架仅针对子串(子数组)问题,使用前也具有一定的条件限制。比如统计数的和或者乘积时数为正数(或非负数),若存在负数那么可能就是其它形如动态规划或贪心求解的最大子数组和问题了。

参考:labuladong

博客首文,不好的地方欢迎提出批评。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值