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