滑动窗口思路:
解决部分数组问题时,设置两个索引下标,为左边界,为右边界,逐渐遍历整个数组,和组成的子数组形成长度变化的滑动窗口,直至遍历完整个数组。
应用一:
Leetcode 3:Longest Substring Without Repeating Characters
在一个字符串中寻找没有重复字母的最长子串,返回长度值。
解法1:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 滑动窗口
result = {}
left = 0
ans = 0
for i, c in enumerate(s):
# 把所有的字符存放在字典里,每次对一个字符进行检查:
# if c在result里,且result[c]的索引>= left【说明字符重复了】
# 更新left为索引值+1
# else 最大子串长度=i-left+1或者当前的最大值
# 更新/添加新字符的索引。【始终保持当前value是某字符索引的最大值】
if c in result and result[c]>=left:
left = result[c]+1
else:
ans = max(i-left+1, ans)
result[c]=i
return ans
解法2:
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
# 滑动窗口,右边界右移,直到找到有重复字符,记录长度,然后将左边界右移到重复的数组+1位置,再继续右移右边界,直到找到新的重复字符
# 时间复杂度O(n),空间复杂度O(1)
freq = [0 for _ in range(256)] # 用于记录每个字符串当前出现频率,索引为每个字符串对应的ASCII码
l = 0
r = -1 # nums[l...r]为滑动窗口
res = 0 # 初始化为最小
while l < len(s):
# 当右边界下一个位置s[r+1]的频率为0时才右移,否则有重复字符,就右移左边界直到没有重复字符
if r < len(s)-1 == 0 and freq[ord(s[r+1])] == 0:
r += 1
freq[ord(s[r])] += 1
else:
freq[ord(s[l])] -= 1
l += 1
# 每次循环中滑动窗口内永远不会有重复字符,所以每次都可以做比较,最终res为最大值
res = max(res, r-l+1)
return res
应用二:
Leetcode 209:Minimum Size Subarray Sum
给定一个整型数组和一个数字s,找到数组中最短的一个连续子数组,使得连续子数组的数字和sum>=s,返回这个最短的连续子数组的长度值。
class Solution(object):
def minSubArrayLen(self, nums):
"""
:type s: int
:type nums: List[int]
:rtype: int
"""
# 滑动窗口,右边界右移,找到一个连续子数组和大于s,记录长度,然后将左边界右移,当和小于s时,再右移右边界,直到找到新的连续子数组
# 时间复杂度O(n),空间复杂度O(1)
l = 0
r = -1 # nums[l...r]为滑动窗口
sums = 0
res = len(nums) + 1 # 初始设为不可能取到的最大值
while l < len(nums):
if sums < s and r < len(nums) - 1:
r += 1
sums += nums[r]
else:
sums -= nums[l]
l += 1
if sums >= s:
res = min(res, r-l+1)
if res == len(nums) + 1:
return 0
return res