文章目录
- 窗口问题一直是一类十分重要的题目,对于是否规定这个窗口的长度,也可以细分为
定长滑动窗口
、不定长滑动窗口
,其中不定长滑动窗口也可以分为求解最长子数组
、求解最短子数组
、求解子数组的个数
- 正所谓
法无定法,在于因时因势
,首先得先掌握这个基础知识,然后在面对新的问题的时候,可以学会灵活变通,学会转化为已经学过的内容
定长滑动窗口
窗口之定长滑动窗口
- 定长滑动窗口,题目会规定这个窗口的值,简单的问题也就是
求解长度为K的子串中某个元素的数量?
,当然难的问题会比较难转化! - 总的来说,定长滑动窗口得弄清楚几个问题:
- 入:下标为
i
的元素进入窗口,更新统计量,如果i<k-1
就重复执行入的操作(下标是从0开始的,所以i<k-1的时候窗口最多只有k-1的元素
) - 更新:更新答案。一般是更新最大值/最小值
- 出:下标为
i-k+1
的元素离开窗口,更新统计量
- 入:下标为
- 下面给出对应的伪代码
python
# 假设求解的窗口为k的字符串(数组)出现的某个字符的最大/最少数目(平均值)
ans = tmp = 0
for i,c in enumerate(s):
# 1.进入窗口
if #对这个字符c进行判断:
#更新这个tmp
if i < k -1:
# 不够k,继续
continue
# 2.满足窗口的长度,更新这个ans
ans = max/min(ans,tmp)
# 3.离开窗口
if s[i-k+1] # 条件判断
# 更新tmp
# ans 就是答案
- 上面的代码由于是伪代码,所以并不是很好理解,所以还是建议结合上面的定长滑动窗口的另一篇博客进行理解
不定长滑动窗口
- 不定长滑动窗口分为:
求解最长子数组
:具体来说,就是求解满足条件的子串或者子数组的最大长度,一般会结合哈希表
记录区间的内的元素的数目求解最短子数组
:和求解这个最长子数组
的解法相似,但是具体的细节的判断要注意求解子数组的个数
:也分为越长越合法
、越短越合法
、恰好型问题
,这个越长、越短、与恰好,是对于条件的限定,也就是类似于区间的和至少为target,至多为target或者刚好为target的子数组的个数
求解最长子数组
- 给出对应的伪代码
python
# 提前有这个left,ans,count
for right,c in enumerate(s):
# 不管怎么样都是先加入这个元素
while # 判断是否满足条件:
# 如果不满足就更新这个left,缩小窗口
ans = max/min # 更新答案
求解最短子数组
- 给出对应的伪代码
python
# 使用left,ans,count
for right ,c in enumerate(s):
# 直接加入新的元素
while count - s[left] >= k? # 就是判断此时要是缩小窗口是否还满足条件
# 如果缩小窗口还满足条件,就缩小窗口
count -= s[left] # 可以替换成其他的操作
left += 1
if count >= k:
# 更新这个ans
求解子数组的个数
越长越合法
:至少满足型
,更新答案的时候,当当前的区间是满足最低标准的时候left左边的全部元素加入窗口都是满足情况的
,所以区间的更新是ans++left
python
# 可以不用这个right 记录
# 提前定义好left ,count
left = count =0
# 直接枚举元素,假设这个是字符串
for c in s:
# 可以借助哈希表进行统计
cnt[c]+= 1
# 判断是否满足情况
while len(cnt)>=k:
# 缩小窗口
out = s[left]
cnt[out] -= 1
if cnt[out] == 0:
del cnt[out]
left += 1
# 更新这个ans
ans += left
越短越合法
- 越短越合法,我们只需找到
满足条件的最大情况
,然后更新答案的时候,这个满足的子数组的个数就是区间的长度
,也就是更新的时候是ans+= right-left+1
python
# 定义left,ans,count
for right,c in enumerate(nums):
# 更新count ,加入新元素
while count >= k: # 求解的是最大的满足情况,所以超过的时候得缩小窗口
# count 减去左端点部分
left += 1
ans += right - left + 1
恰好型
- 恰好型:计算多少个元素
恰好等于k
的子数组,可以变化为- 计算有多少个元素和
>=k
的子数组 - 计算有多少个元素和
>=k+1
的子数组
- 计算有多少个元素和
- 最终的答案就是
f(k)-f(k+1)