1 引言
积跬步以至千里,积怠情以至深渊。
本文主要介绍leetcode中关于窗口滑动类的问题及其解题模板。
2 窗口滑动类问题
滑动窗口这类问题一般需要用到 双指针 来进行求解,一般都是基于字符串和数组的。在leetcode中题目(3、76、239、424、438、480、567、992、995、978、1040、1052、1074、1028)的大致问法如下:
- 给两个字符串,一长一短,问其中短的是否在长的中满足一定的条件存在,例如:
求长的的最短子串,该子串必须涵盖短的的所有字符;
短的的 anagram 在长的中出现的所有位置;
… - 给一个字符串或者数组,问这个字符串的子串或者子数组是否满足一定的条件,例如:
含有少于 k 个不同字符的最长子串;
所有字符都只出现一次的最长子串;
…
2 解题模板
import collections
def solution(s, ...):
# 首先是对输入的参数进行有效性判断
if ...:
...
# 利用collections库创建一个hash,用于记录窗口中具体元素的个数情况
# 也可以使用字典等其他数据结构
count = collections.Counter(...)
# 选择性的进行数据预处理
...
left = 0 # 定义左指针
cond = ... # 记录当前的条件,具体应该根据题目要求来定义
result = ... # 用来存放结果
# 开始移动右指针
for right in range(len(s)):
# 更新count中元素的数量,此处若是处理字符串之间的关系问题,用-1;若是处理字符串内部关系问题,用+1
count[s[right]] -= 1 # 之所以-1的原因在于方便对比与另一字符串元素之间的数量差
# 根据窗口的变更结果来改变条件值
if count[s[right]] == ...:
cond += 1
# 如果当前条件不满足,移动左指针直至条件满足为止
while cond > K or ...:
...
if ...:
cond -= 1
count[s[left]] += 1 # 此处+1可与以上的-1相抵消
left += 1
# 更新结果
result = ...
return result