一、定长滑动窗口
定长滑动窗口,每次移动窗口时移除窗口旧尾部元素的贡献,添加窗口新头部元素的贡献。
1456. 定长子串中元音的最大数目
板子,每次移动窗口时若新头部元素为元音则计数加 1 1 1,若旧尾部元素为元音则计数减 1 1 1。
643. 子数组最大平均数 I
板子。
1343. 大小为 K 且平均值大于等于阈值的子数组数目
板子。
2090. 半径为 k 的子数组平均值
注意窗口的长度是 2 k + 1 2k+1 2k+1,不保证小于等于数组总长度 n n n。
2379. 得到 K 个黑块的最少涂色次数
转化为“黑色块最多(白色块最少)的窗口”。
1052. 爱生气的书店老板
窗口内全 0 0 0,每次移动窗口时若新头部元素为 1 1 1 则加上对应贡献,若旧尾部元素为 1 1 1 则减去对应贡献。
2841. 几乎唯一子数组的最大和
用 map
和一个计数器维护窗口内互不相同的元素的个数,另一个计数器维护窗口内元素和。满足“有至少
m
m
m 个互不相同的元素”时用当前窗口内元素和更新答案。
下一题同理,互不相同元素数等于 k k k 时更新答案。
1423. 可获得的最大点数
只拿两头的 k k k 张转化为不拿中间的 n − k n-k n−k 张,实际上是求长度为 n − k n-k n−k 的窗口的最小元素和。
1652. 拆炸弹
维护窗口元素和后赋值给对应位置即可,使用取模计算循环性。
1461. 检查一个字符串是否包含所有长度为 K 的二进制子串
注意到 k ≤ 20 k\leq20 k≤20,则二进制子串可以转化为十进制整数从而开桶计数。移动窗口时删掉最高位并填上新的最低位。
2134. 最少交换次数来组合所有的 1 II
一开始看错题了,以为是相邻元素交换,我检讨。
窗口长度为 1 1 1 的总个数,因为窗口中每一个 0 0 0 都可以通过一步交换变成 1 1 1,所以实际上是计算窗口中 0 0 0 的最少个数。
1297. 子串的最大出现次数
注意到较短的子串实际上被较长的子串完全包含,所以事实上只需要计算长度为 minSize
的子串。
用哈希表维护子串的出现个数(实际上用了 map
😋)。
2653. 滑动子数组的美丽值
因为数组元素值范围极小,所以可以用一个桶维护窗口内元素的出现次数,通过从小到大遍历桶找到第 x 小整数。
1888. 使二进制字符串字符交替的最少反转次数
将字符串复制一份拼接成长度为 2 n 2n 2n 的字符串,然后用长度为 n n n 的滑动窗口维护类型 1 的循环性。
注意到每个窗口有两种交替方式,即 10101...
和 01010...
,两种方式所需的翻转次数之和为
n
n
n。如果固定整个串的奇数位为
1
1
1,偶数位为
0
0
0 作为一种方式,则很方便在窗口移动时更新翻转次数,顺便计算出另一种方式所需的次数。
567. 字符串的排列
注意到字符串 a
是字符串 b
排列当且仅当 a
与 b
中字母的种类和个数相同。开一个 map
维护窗口中各个字母的出现个数,数据范围完全支持我们每次移动窗口时遍历
26
26
26 个字母判断出现个数是否与 s1
相同。
438. 找到字符串中所有字母异位词
和上一题一样的思路。
30. 串联所有单词的子串
把 s
按 words
中字符串的长度分割成字符串数组,以 words
的大小作为滑动窗口的大小,以字符串为比对单位,按照前两题的思路用 map
统计字符串出现个数从而判断串联子串。
由于不同的分割点会分割出不同的字符串数组,所以枚举 s
中前 words[i].length
个字母作为分割的起始点。
2156. 查找给定哈希值的子串
其实很板,移动的时候把最后一位对应的哈希值减去就行。
2953. 统计完全子字符串
每个字符恰好出现 k k k 次,所以移动窗口的大小是 k k k 的整数倍。
对于条件 1 1 1,移动窗口移动的时候用桶和计数器维护一下有多少少于 k k k 个的,有多少多于 k k k 个的。对于条件 2 2 2,计数一下相差大于 2 2 2 的组数。然后当三个计数器都为 0 0 0 时统计一个答案。
1016. 子串能表示从 1 到 N 数字的二进制串
和 1461 差不多。
未完待续