滑动窗口可以归类为快慢指针,一快一慢两个指针前后相随,中间的部分就是窗口。
滑动窗口算法技巧主要用来解决子数组问题,比如让你寻找符合某个条件的最长/最短子数组。
滑动窗口框架概览
如果使用暴力解法,需要嵌套for循环实现穷举所有子数组,时间复杂度是N^2
for (int i = 0; i < nums.length; i++) {
for (int j = i; j < nums.length; j++) {
// nums[i, j] 是一个子数组
}
}
如果使用滑动框架,简单的来说就是维护一个窗口,不断滑动,然后更新答案
int left , right = 0;
while (right <nums.size()){
// 增大窗口
window.addLast(nums[right]);
right ++;
while(window needs shrink){
// 缩小窗口
window.removeFirst(nums[left]);
left++;
}
}
基于滑动窗口框架写出的代码时间复杂度是O(N)
- 滑动窗口伪代码实现:
# 滑动窗口算法伪码框架
def slidingWindow(s: str):
# 用合适的数据结构记录窗口中的数据,根据具体场景变通
# 比如说,我想记录窗口中元素出现的次数,就用 map
# 如果我想记录窗口中的元素和,就可以只用一个 int
window = ...
left, right = 0, 0
while right < len(s):
# c 是将移入窗口的字符
c = s[right]
window.add(c)
# 增大窗口
right += 1
# 进行窗口内数据的一系列更新
...
# *** debug 输出的位置 ***
# 注意在最终的解法代码中不要 print
# 因为 IO 操作很耗时,可能导致超时
# print(f"window: [{left}, {right})")
# ***********************
# 判断左侧窗口是否要收缩
while left < right and window needs shrink:
# d 是将移出窗口的字符
d = s[left]
window.remove(d)
# 缩小窗口
left += 1
# 进行窗口内数据的一系列更新
...
__END__