滑动窗口
滑动窗口实际上也是双指针的应用,滑动窗口的右指针不断扩大窗口的范围,当窗口内的对象符合某个条件时,进行统计或者某种操作;然后左指针收缩窗口来打破条件,以便让右指针右移继续扩大窗口
滑动窗口题目:
3. 无重复字符的最长子串(使用左右指针构造一个滑动窗口,确保滑动窗口内的子串满足要求)
30. 串联所有单词的子串
76. 最小覆盖子串
159. 至多包含两个不同字符的最长子串
209. 长度最小的子数组
239. 滑动窗口最大值
567. 字符串的排列
632. 最小区间
727. 最小窗口子序列
3. 无重复字符的最长子串
解题思路:定义一个数组作为滑动窗口,如果一个字符不在窗口内,则加入;反之,从左边开始删除滑动窗口内的字符来调整窗口;
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
i = 0
windowArr = []
max_len = 0
while i<len(s):
if s[i] not in windowArr:
windowArr.append(s[i])
i+=1
max_len = max(max_len, len(windowArr))
else:
while s[i] in windowArr:
windowArr.pop(0)
return max_len
76. 最小覆盖子集
思路:使用一个字典来统计滑动窗口内每个字符以及出现的次数,
如果窗口内字符以及出现的次数跟目标字符串一致时,则统计窗口内字符的长度,然后将左指针往前移动来缩减窗口,直到窗口内匹配的字符个数少于目标字符串时;
如果匹配的个数少于目标字符串时,不断右指针往前移动,来扩大窗口的范围;
当右指针直到s字符串的最后一个字符时,算法结束
class Solution:
def minWindow(self, s: str, t: str) -> str:
if not t or not s:
return ""
dic = collections.Counter(t)
required = len(dic)
l, r = 0, 0
formed = 0
windowCounts = {}
ans = float("inf"), None, None
while r < len(s):
character = s[r]
windowCounts[character] = windowCounts.get(character, 0) + 1
if character in dic and windowCounts[character] == dic[character]:
formed += 1
while l <= r and formed == required:
character = s[l]
if r - l + 1 < ans[0]:
ans = (r - l + 1, l, r)
windowCounts[character] -= 1
if character in dic and windowCounts[character] < dic[character]:
formed -= 1
l += 1
r += 1
return "" if ans[0] == float("inf") else s[ans[1] : ans[2] + 1]
159:至多包含两个不同字符的最长子串
思路:
用左右指针来构建一个滑动窗口,
当窗口内的不同字符个数<=2时,右指针右移来扩大窗口,并统计窗口的长度;
当窗口内不同字符的个数>2时,左指针右移来缩小窗口
class Solution:
def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
if len(s)<3:
return len(s)
i, j = 0, 0
max_len = 0
while j<len(s):
if len(set(s[i:j+1]))<=2:
max_len = max(max_len, j-i+1)
j+=1
else:
while i<=j and len(set(s[i:j+1]))>2:
i+=1
return max_len
209 长度最小的子数组
使用左右指针来构建一个滑动窗,
当窗口内的数字的和<s时,右指针右移来扩大窗口;
当窗口内的数字之和>=s时,统计窗口的长度,并将左指针右移来缩小窗口
class Solution:
def minSubArrayLen(self, s: int, nums: List[int]) -> int:
if not nums:
return 0
i, j = 0, 0
windowSum = 0
min_len = float('inf')
while j<len(nums):
windowSum += nums[j]
while i<=j and windowSum>=s:
min_len = min(min_len, j-i+1)
windowSum -= nums[i]
i+=1
j+=1
return 0 if min_len == float('inf') else min_len