【五月集训】Day06——滑动窗口


前言

        第六天:滑动窗口
        滑动窗口主要针对于数组的求解,在对给定窗口长度范围内的数组或字符串进行操作时,在遍历过程中,前后两个窗口难免会有重叠部分,可省区重叠部分的计算,只计算两端新出现的数字或字符即可,具体实例可参考第四道练习题目《爱生气的书店老板》。


一、练习题目

题目链接难度
1984. 学生分数的最小差值★☆☆☆☆
1876. 长度为三且各字符不同的子字符串★☆☆☆☆
1839. 所有元音按顺序排布的最长子字符串★★☆☆☆
1052. 爱生气的书店老板★★☆☆☆

二、思路与代码

1. 学生分数的最小差值

        给你一个下标从0开始的整数数组nums ,其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。从数组中选出任意 k 名学生的分数,使这k个分数间最高分和最低分的差值达到最小化 。返回可能的最小差值 。

解题思路:
对数组排序,则给定窗口范围内的最小差值只会出现在相邻的子数组里,遍历数组找到最小差值即可。

class Solution(object):
    def minimumDifference(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        nums.sort()
        n = len(nums)
        minDistance = nums[k-1] - nums[0]
        for i, num in enumerate(nums):
            if i+k-1 < n:
                if nums[i+k-1] - nums[i] < minDistance:
                    minDistance = nums[i+k-1] - nums[i]
        return minDistance

2.长度为三且各字符不同的子字符串

题目描述
        如果一个字符串不含有任何重复字符,我们称这个字符串为 好 字符串。给你一个字符串 s ,请你返回 s 中长度为 3 的 好子字符串 的数量。注意,如果相同的好子字符串出现多次,每一次都应该被记入答案之中。子字符串 是一个字符串中连续的字符序列。示例

解题思路:
遍历字符串,找到给定窗口长度,且符合要求的子字符串个数即可。

class Solution(object):
    def countGoodSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
    
        cnt = 0
        for i, ch in enumerate(s):
            if i + 2 < len(s):
                if ch != s[i+1] and ch != s[i+2] and s[i+1] != s[i+2]:
                    cnt += 1
        return cnt 

3.所有元音按顺序排布的最长子字符串

        题目描述示例

解题思路:
1)主要目标是希望从给定字符串中找到符合条件的最大字符串的长度;
2)设定左右两个指针,右指针用来遍历字符串,如果右指针符合条件,继续遍历,如果不符合条件,将右指针位置赋值给左指针,右指针接着遍历;
3)如果左右指针所包括的窗口范围内的字符串符合条件,则记录该窗口的区间长度;
4)返回最大区间长度。

class Solution(object):
    def longestBeautifulSubstring(self, word):
        """
        :type word: str
        :rtype: int
        """
        distance = 0 #记录最长美丽字符串的长度
        cnt = 1 #记录滑动窗口内字符种类
        i = 0 # 左指针
        for j in range(1, len(word)):  
            if word[j] < word[j-1]: #如果右指针小于前一个字符,将右指针的值赋值给左指针
                i = j
                cnt = 1
            elif word[j] > word[j-1]: #如果右指针大于前一个字符,字符种类加一
                cnt += 1
            if cnt == 5:
                distance = max(distance, j-i+1)           
        return distance

4.爱生气的书店老板

        题目描述示例

解题思路:
1)记录未使用技巧时,顾客满意个数;
2)在大小为minutes的滑动窗口里,找到老板使用技巧后新增的最大顾客个数;
3)两者相加。

class Solution(object):
    def maxSatisfied(self, customers, grumpy, minutes):
        """
        :type customers: List[int]
        :type grumpy: List[int]
        :type minutes: int
        :rtype: int
        """
        sumT = 0 #用来记录老板在不适用技巧时,顾客满意个数
        increT = 0 #记录老板使用技巧后,新增的最大顾客满意个数
        
        for i in range(len(grumpy)):
            if grumpy[i] == 0:
                sumT += customers[i] 
        for i in range(minutes): #前minutes时间里新增顾客满意个数初值
            if grumpy[i] == 1:
                increT += customers[i]

        tmp = increT #滑动窗口内,新增顾客满意个数
        for i in range(minutes, len(grumpy)):      
            if grumpy[i] == 1:
                tmp += customers[i]
            if grumpy[i-minutes] == 1:
                tmp -= customers[i-minutes]
            increT = max(tmp, increT) #比较,最后得出使用技巧后最大新增顾客数
        return sumT + increT

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值