定长滑动窗口算法详细解释(带例题的详细解法)

本文参考:

灵茶山艾府

题单:分享丨【题单】滑动窗口(定长/不定长/多指针) - 力扣(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语言:

可以查看我的题解:

1456. 定长子串中元音的最大数目 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-number-of-vowels-in-a-substring-of-given-length/solutions/2846816/1456-ding-chang-hua-dong-chuang-kou-yi-d-dnq8/

例题二:

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语言:

可以查看我的题解:

643. 子数组最大平均数 I - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/maximum-average-subarray-i/solutions/2847355/ti-hao-643-jing-dian-ding-chang-hua-dong-1xhk/

  • 28
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值