本文参考:
题单:分享丨【题单】滑动窗口(定长/不定长/多指针) - 力扣(LeetCode)
个人觉得我对滑动窗口的解释好理解一些(bushi)
定长滑动窗口通用解法
首先要明确题目要求,是否可以使用滑动窗口做,这个窗口是否长度是固定的
通用解法:
计算处理初始窗口:根据题目相关要求,求出初始滑动窗口的一个当前值current
元素进入:窗口右边元素进入窗口,修改current的值
元素移除:窗口左边元素移除窗口,修改current的值
更新答案:根据题目要求和此时的current更新答案result
例题一:
1456. 定长子串中元音的最大数目 - 力扣(LeetCode)
题目描述解析:
给你字符串 s
和整数 k
。
请返回字符串 s
中长度为 k
的单个子字符串中可能包含的最大元音字母数。
题目的意思是找在字符串s中连续长度为k的子字符串中包含元音字符的最大数目
暴力解法尝试:
当然这里可以有一个暴力解法:
先遍历数组,然后遍历到每一个下标的时候,从这个下标开始遍历长度为k,统计数量,暴力解法代码如下(Python):
class Solution:
def maxVowels(self, s: str, k: int) -> int:
def is_vowel(c):
if c in "aeiou":
return 1
else: return 0
res = 0
for i in range(len(s)):
cur = 0
for j in range(i, min((i + k), len(s))):#防止超出范围
cur += is_vowel(s[j])
res = max(res, cur)
return res
很明显,这个的时间复杂度为O(n * k),当数据量过大的时候,这个代码运行效率会很低,甚至会超时:
滑动窗口思路:
那么现在会有一个新思路,就是滑动窗口:
先求出起始长度为k的子字符串中元音字母的数量cur(current缩写),然后遍历字符串,定长窗口向前滑动。
每当定长窗口滑动的时候,窗口左端的元素会移出窗口,右端元素会加入窗口。
则只需判断进入和移除的元素即可。
移除的元素是元音字母,当前窗口元音字母数量cur--
进入的元素是元音字母,当前窗口元音字母数量cur++
求出这个过程中cur的最大值即可
实际例子理解:
可以通过示例1走一遍:
s = "abciiidef", k = 3
先求出起始长度为k = 3中的子字符串元音字母数量cur
abc, cur = 1
窗口向前移动,窗口移除字符a,进入字符i,进入一个元音,移除一个元音,cur -= 1, cur += 1,此时
cur = 1
再次移动,窗口移除字符b, 进入字符i,进入一个元音,移除一个非元音,cur -= 0, cur += 1,此时cur = 2
再次移动,窗口移除字符c, 进入字符i,进入一个元音,移除一个非元音,cur -= 0, cur += 1,此时cur = 3
再次移动,窗口移除字符i, 进入字符d,进入一个非元音,移除一个元音,cur -= 1, cur += 0,此时cur = 2
再次移动,窗口移除字符i, 进入字符e,进入一个元音,移除一个元音,cur -= 1, cur += 1,此时
cur = 2
再次移动,窗口移除字符i, 进入字符f,进入一个非元音,移除一个元音,cur -= 1, cur += 0,此时cur = 1
则最大值为3
代码(Python):
class Solution:
def maxVowels(self, s: str, k: int) -> int:
def is_vowel(c):
if c in "aeiou":
return 1
else: return 0
#计算处理初始窗口:根据题目相关要求,求出初始滑动窗口的一个当前值current
cur, n = 0, len(s)
for i in range(k):
cur += is_vowel(s[i])
res = cur
for i in range(k, n):
cur -= is_vowel(s[i - k])#元素进入:窗口右边元素进入窗口,修改current的值
cur += is_vowel(s[i])#元素移除:窗口左边元素移除窗口,修改current的值
res = max(cur, res)#更新答案:根据题目要求和此时的current更新答案result
return res
C++,Java,Go语言:
可以查看我的题解:
例题二:
643. 子数组最大平均数 I - 力扣(LeetCode)
题目描述解析:
题目要求在长度为k的连续子数组中平均数的最大值,由于k是固定的,则只需要求出在这个固定长度区间内的最大值即可
滑动窗口思路:
先求出起始长度为k的区间内的元素和sumVal
然后遍历字符串,定长窗口向前滑动。
每当定长窗口滑动的时候,窗口左端的元素会移出窗口,右端元素会加入窗口。
左端移除窗口,则sumVal -= 移除元素
右端进入窗口,则sumVal += 进入元素
求这个过程中是sumVal的最大值即可
注意题目需要返回的是double类型
代码(Python):
class Solution:
def findMaxAverage(self, nums: List[int], k: int) -> float:
n = len(nums)
#sum_val = sum(nums[:k]) 也可以
sum_val = 0
for i in range(k):
sum_val += nums[i]
res = sum_val
for i in range(k, n):
sum_val -= nums[i - k]
sum_val += nums[i]
res = max(sum_val, res)
return res / k
C++,Java,Go语言:
可以查看我的题解: