其实滑动窗口就是变相的双指针,不停加入right
达到“条件”后开始缩减窗口(移动left),打擂台挑出正确值
lc.209长度最小的子数组
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = 0
right = 0
window_sum = 0
min_len = float('inf')
while right < len(nums):
#无脑加入right
window_sum += nums[right]
#达到收割结果条件
while window_sum >= target:
min_len = min(min_len, right - left + 1)
window_sum -= nums[left]
left += 1
#开始加入下一个right
right += 1
if min_len == float('inf'):
return 0
return min_len
lc.904水果成篮
使用Counter记录每个果子的数量
此题和lc209的区别在于,我们达到条件的部分在下方
内部的while用于处理超出题目条件的情况
因此下方的left和right一定满足了题目条件
1、无脑添加right
2、不收割,调整window使得符合条件
3、收割
4、添加下一个right
class Solution:
from collections import Counter
def totalFruit(self, fruits: List[int]) -> int:
left = 0
right = 0
max_len = float('-inf')
my_dict = Counter()
while right < len(fruits):
#无脑加入right
my_dict[fruits[right]] += 1
#这里不收割,而是处理掉不满足题目条件的情况
while len(my_dict) > 2:
my_dict[fruits[left]] -= 1
if my_dict[fruits[left]] == 0:
my_dict.pop(fruits[left])
left += 1
#上方while处理了,这里就一定满足题目条件了
max_len = max(max_len, right - left + 1)
#开始加入下一个right
right += 1
return max_len
lc.76最小覆盖子串
还是按照我总结的模版:
1、无脑添加right(扩张window)
2、收割并尝试移动left(收缩window)
3、添加下一个right
class Solution:
from collections import Counter
from collections import deque
def minWindow(self, s: str, t: str) -> str:
left = 0
right = 0
min_len = float('inf')
min_left = 0
t_dict = Counter(t)
s_dict = Counter()
while right < len(s):
#无脑添加right
s_dict[s[right]] += 1
#符合条件收割
while all(s_dict[char] >= t_dict[char] for char in t_dict.keys()):
sub_len = right - left + 1
#记录最小长度和其左开头index
if sub_len < min_len:
min_len = sub_len
min_left = left
#缩小滑动窗口
s_dict[s[left]] -= 1
left += 1
#添加下一个right
right += 1
if min_len == float('inf'):
return ""
res = s[min_left:min_left + min_len]
return res