滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
定长滑动窗口
核心思路:入,更新,出
1456. 定长子串中元音的最大数目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution:
def maxVowels(self, s: str, k: int) -> int:
res, win = 0, 0
for idx, char in enumerate(s):
"""in"""
if char in 'aeiou':
win += 1
if idx < k - 1:
continue
"""update"""
res = max(res, win)
"""out"""
if s[idx-(k-1)] in 'aeiou':
win -= 1
return res
|
643. 子数组最大平均数 I
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def findMaxAverage(self, nums: List[int], k: int) -> float:
res, win = -float('inf'), 0
for idx, num in enumerate(nums):
""" 入 """
win += num
if idx < k - 1: continue
"""更新"""
res = max(res, win/k)
"""出"""
win -= nums[idx-k+1]
return res
|
1343. 大小为 K 且平均值大于等于阈值的子数组数目
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def numOfSubarrays(self, arr: List[int], k: int, threshold: int) -> int:
res, win = 0, 0
for idx, num in enumerate(arr):
"""入"""
win += num
if idx < k - 1: continue
"""更新"""
res += int(win >= k * threshold)
"""出"""
win -= arr[idx-k+1]
return res
|
2090. 半径为 k 的子数组平均值
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def getAverages(self, nums: List[int], k: int) -> List[int]:
res, win = [-1]*len(nums), 0
for idx, num in enumerate(nums):
"""入"""
win += num
if idx < 2 * k: continue
"""错位更新"""
res[idx-k] = win // (2*k+1)
"""出"""
win -= nums[idx-2*k]
return res
|
2379. 得到 K 个黑块的最少涂色次数
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def minimumRecolors(self, blocks: str, k: int) -> int:
res, win = float('inf'), 0
for idx, block in enumerate(blocks):
"""入"""
win += int(block == 'W')
if idx < k - 1: continue
"""更新"""
res = min(res, win)
"""出"""
win -= int(blocks[idx-k+1] == 'W')
return res
|
2841. 几乎唯一子数组的最大和
注意Counter和zip的用法,这两个让我们一方面可以快速遍历滑动窗口,一方面可以高效实现统计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
class Solution:
def maxSum(self, nums: List[int], m: int, k: int) -> int:
res, win, cnt = 0, sum(nums[:k-1]), Counter(nums[:k-1])
"""
res: 用于存储最终结果,即满足条件的子数组的最大和
win: 当前窗口的和,初始化为前k-1个元素的和
cnt: 当前窗口中各元素的计数器,初始化为前k-1个元素的计数
"""
for head, tail in zip(nums[k-1:], nums):
"""
head: 窗口新增加的元素
tail: 窗口将要移除的元素
"""
win += head # 将新元素加入窗口和
cnt[head] += 1 # 更新新元素的计数
if len(cnt) >= m:
# 如果窗口内唯一元素的数量大于或等于m
res = max(res, win) # 更新结果为当前和与之前最大和中的较大值
cnt[tail] -= 1 # 减少将要移除元素的计数
win -= tail # 从窗口和中减去将要移除的元素
if not cnt[tail]:
# 如果将要移除的元素在窗口中的计数为0
del cnt[tail] # 从计数器中删除该元素
return res # 返回找到的最大和
|
2461. 长度为 K 子数组中的最大和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class Solution:
def maximumSubarraySum(self, nums: List[int], k: int) -> int:
# 初始化结果变量,窗口和,以及计数器
res, win, cnt = 0, sum(nums[:k-1]), Counter(nums[:k-1])
# 使用滑动窗口,遍历数组
for head, tail in zip(nums[k-1:], nums):
# 将新元素加入窗口,并更新窗口的和与计数器
win += head
cnt[head] += 1
# 如果窗口中 unique 元素的数量等于 k,则更新结果
if len(cnt) == k:
res = max(res, win)
# 移除窗口中最旧的元素,更新窗口的和与计数器
win -= tail
cnt[tail] -= 1
if cnt[tail] == 0:
del cnt[tail]
# 返回最终结果
return res
|
1423. 可获得的最大点数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Solution:
def maxScore(self, cardPoints: List[int], k: int) -> int:
# 计算窗口大小,即需要保留的连续子数组的长度
size = len(cardPoints) - k
# 如果窗口大小为0,表示需要取走所有卡片,直接返回总和
if not size:
return sum(cardPoints)
# 初始化最小和为无穷大,窗口和为前size-1个元素的和
res, win = float('inf'), sum(cardPoints[:size-1])
# 使用滑动窗口遍历数组
for head, tail in zip(cardPoints[size-1:], cardPoints):
# 将新元素加入窗口,更新窗口和
win += head
# 更新最小窗口和
res = min(res, win)
# 移除窗口中最旧的元素,更新窗口和
win -= tail
# 返回总和减去最小窗口和,即为最大抽取和
return sum(cardPoints) - res
|
1052. 爱生气的书店老板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
class Solution:
def maxSatisfied(self, customers, grumpy, minutes: int) -> int:
"""
计算在给定时间窗口内,商店最多可以满足的客户数。
参数:
- customers: List[int],表示每个时间点进入商店的客户数量。
- grumpy: List[int],表示商店老板在每个时间点是否生气(1表示生气,0表示不生气)。
- minutes: int,表示商店老板可以控制不生气的时间窗口长度。
返回:
- int,表示在最优控制下,商店可以满足的最多客户数。
"""
# 计算没有控制生气情况下,自然不生气时间点的客户数总和
base = 0
for i, j in zip(customers, grumpy):
base += i * (1 - j)
# 初始化变量,用于计算通过控制不生气可以额外满足的客户数
incr, win = 0, 0
# 使用滑动窗口计算在不同窗口内,可以额外满足的客户数
for i in range(len(customers)):
win += customers[i] * grumpy[i]
if i < minutes - 1:
continue
incr = max(incr, win)
win -= customers[i - minutes + 1] * grumpy[i - minutes + 1]
# 返回基础满意的客户数加上额外可以满意的最多客户数
return base + incr
|
1652. 拆炸弹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class Solution:
def decrypt(self, code: List[int], k: int) -> List[int]:
"""
解密给定的代码列表。
参数:
- code: List[int],表示加密的代码列表。
- k: int,表示解密的偏移量。
返回:
- List[int],表示解密后的代码列表。
"""
# 初始化结果列表,长度与 code 相同,全部元素为 0
res = [0] * len(code)
n = len(code)
# 将 code 列表扩展一倍,以便处理循环索引
code.extend(code)
if not k:
# 如果 k 为 0,直接返回全零列表
return res
elif k < 0:
# 如果 k 为负数,向左移动 |k| 个位置
for i in range(n):
# 计算从 i + k + n 到 i + n 的子列表的和
res[i] = sum(code[i + k + n : i + n])
elif k > 0:
# 如果 k 为正数,向右移动 k 个位置
for i in range(n):
# 计算从 i + 1 到 i + k + 1 的子列表的和
res[i] = sum(code[i + 1 : i + k + 1])
return res
|
3439. 重新安排会议得到最多空余时间 I
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
class Solution:
def maxFreeTime(self, eventTime: int, k: int, startTime: List[int], endTime: List[int]) -> int:
"""
计算在给定事件时间内,最大的空闲时间长度。
参数:
- eventTime: int,总事件时间长度。
- k: int,表示窗口大小或限制。
- startTime: List[int],表示各事件的开始时间列表。
- endTime: List[int],表示各事件的结束时间列表。
返回:
- int,表示最大的空闲时间长度。
"""
# 计算事件之间的空闲时间间隔
gap, n = [], len(startTime)
for i in range(n + 1):
if not i:
# 第一个事件开始前的空闲时间
gap.append(startTime[0])
elif i == n:
# 最后一个事件结束后到总时间结束的空闲时间
gap.append(eventTime - endTime[i - 1])
else:
# 相邻事件之间的空闲时间
gap.append(startTime[i] - endTime[i - 1])
# 初始化窗口总和和结果变量
win, res = 0, 0
# 使用滑动窗口计算最大空闲时间
for i in range(len(gap)):
win += gap[i]
if i < k:
continue
res = max(res, win)
win -= gap[i - k]
return res
|
2134. 最少交换次数来组合所有的 1 II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
class Solution:
def minSwaps(self, nums: List[int]) -> int:
"""
计算将所有1聚在一起所需的最小交换次数。
参数:
- nums: List[int],一个包含0和1的整数列表。
返回:
- int,表示将所有1聚在一起所需的最小交换次数。
"""
n, k = len(nums), sum(nums)
if not k:
return 0 # 如果没有1,不需要任何交换
# 将 nums 扩展一倍,处理环形情况
nums.extend(nums)
# 初始化窗口内1的个数和结果变量
win, res = 0, 0
# 使用滑动窗口计算窗口内1的最大个数
for i in range(2 * n):
win += nums[i]
if i < k - 1:
continue # 窗口尚未形成,继续添加
res = max(res, win) # 更新窗口内1的最大个数
win -= nums[i - k + 1] # 移除窗口最左边的元素
# 最小交换次数等于窗口大小 k 减去窗口内1的最大个数 res
return k - res
|
1297. 子串的最大出现次数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
from collections import Counter
class Solution:
def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int:
"""
这个函数用于找到字符串s中满足特定条件的子字符串的最高出现频率。
参数:
- s: 目标字符串,类型为str
- maxLetters: 子字符串中允许的最大不同字符数,类型为int
- minSize: 子字符串的最小长度,类型为int
- maxSize: 子字符串的最大长度,类型为int
返回:
- 满足条件的子字符串的最大出现次数,类型为int
"""
# 使用两个计数器:cnt1跟踪当前窗口内每个字符的出现次数,cnt2跟踪满足条件的子字符串的出现次数
cnt1, cnt2 = Counter(), Counter()
res = 0 # 用来记录最高出现次数的结果变量
# 遍历字符串s,i为当前窗口的结束索引
for i in range(len(s)):
cnt1[s[i]] += 1 # 将当前字符加入cnt1
# 如果窗口大小还没达到minSize,跳过后面的检查
if i < minSize - 1:
continue
# 计算窗口的起始索引
j = i - minSize + 1
# 当窗口大小达到minSize时,开始检查条件
if len(cnt1) <= maxLetters:
# 提取子字符串
sub = s[j:i+1]
# 更新cnt2,记录该子字符串的出现次数
cnt2[sub] += 1
# 更新结果变量,取当前结果和cnt2[sub]的最大值
res = max(res, cnt2[sub])
# 移动窗口起始位置,移除起始处的字符,并更新cnt1
cnt1[s[j]] -= 1
if cnt1[s[j]] == 0:
del cnt1[s[j]]
# 遍历完成后,返回最高出现次数
return res
|
不定长滑动窗口
不定长滑动窗口主要分为三类:求最长子数组,求最短子数组,以及求子数组个数。
求最长/最大子数组
3. 无重复字符的最长子串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
"""
计算字符串 s 中最长的无重复字符子串的长度。
参数:
s (str): 输入的字符串
返回:
int: 最长无重复字符子串的长度
"""
# 使用 defaultdict 来记录字符出现的频率
cnt = defaultdict(int)
# res 记录最大不重复子串的长度,l 是滑动窗口的左边界
res, l = 0, 0
# 遍历字符串 s,r 是滑动窗口的右边界
for r, c in enumerate(s):
"""
对于每一个右边界 r,检查字符 s[r] 是否已经在 cnt 中:
- 如果已经在 cnt 中,说明窗口内有重复字符,需要循环移动左边界 l
- 如果不在 cnt 中,将字符加入 cnt,并更新最大长度 res
"""
# 如果当前字符 s[r] 已经在 cnt 中,说明窗口内有重复字符
while cnt[s[r]]:
# 移除左边界的字符,并更新 cnt 和 l
cnt[s[l]] -= 1
# 如果某个字符的计数变为0,从 cnt 中删除该字符
if cnt[s[l]] == 0:
del cnt[s[l]]
l += 1
# 当前字符 s[r] 不在 cnt 中,加入 cnt
cnt[s[r]] += 1
# 更新最大长度 res
res = max(res, r - l + 1)
return res
|
3090. 每个字符最多出现两次的最长子字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
from typing import List
from collections import defaultdict
class Solution:
def maximumLengthSubstring(self, s: str) -> int:
"""
计算字符串 s 中最长的子串长度,该子串中每个字符最多出现两次。
参数:
s (str): 输入的字符串
返回:
int: 符合条件的最长子串长度
"""
# 使用 defaultdict 来记录字符出现的频率
cnt = defaultdict(int)
# res 记录满足条件的最长子串长度,l 是滑动窗口的左边界
res, l = 0, 0
# 遍历字符串 s,r 是滑动窗口的右边界
for r, c in enumerate(s):
"""
对于每一个右边界 r,检查字符 s[r] 在 cnt 中的频率:
- 如果字符 s[r] 的频率已经达到2,需要移动左边界 l,直到 s[r] 的频率小于2
- 如果字符 s[r] 的频率小于2,将其加入 cnt,并更新最大长度 res。
"""
# 如果当前字符 s[r] 的频率已经等于2,需要移动左边界
while cnt[s[r]] == 2:
# 减少左边界的字符频率,如果频率为0则从 cnt 中移除
cnt[s[l]] -= 1
if cnt[s[l]] == 0:
del cnt[s[l]]
l += 1
# 增加当前字符 s[r] 的频率
cnt[s[r]] += 1
# 更新最大长度 res
res = max(res, r - l + 1)
return res
|
1493. 删掉一个元素以后全为 1 的最长子数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
from typing import List
class Solution:
def longestSubarray(self, nums: List[int]) -> int:
"""
计算数组 nums 中最长的子数组长度,该子数组可以包含至多一个零。
参数:
nums (List[int]): 输入的整数数组,只包含0和1。
返回:
int: 符合条件的最长子数组长度
"""
# res 记录最大子数组长度,zero 记录当前窗口内零的个数,l 是滑动窗口的左边界
res, zero, l = 0, 0, 0
# 遍历数组 nums,r 是滑动窗口的右边界
for r, num in enumerate(nums):
"""
对于每一个右边界 r,检查 num 是否为零:
- 如果 zero 已经为1且 num 为零,需要移动左边界 l,直到窗口内零的个数小于1。
- 如果 zero 小于1,将 num 加入窗口,并更新最大长度 res。
"""
# 如果 zero 已经为1且 num 为零,移动左边界直到窗口内零的个数小于1
while zero == 1 and not num:
# 如果左边界的数为零,zero 减1
if not nums[l]:
zero -= 1
l += 1
# 如果 num 为零,zero 加1
zero += int(not num)
# 更新最大长度 res
res = max(res, r - l + 1)
# 由于题目要求至少删除一个元素,所以结果减1
return res - 1
|
1208. 尽可能使字符串相等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
from typing import List
class Solution:
def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
"""
计算两个字符串 s 和 t 的最长公共子串长度,
其中可以进行字符转换,每次转换的代价是两个字符的 ASCII 码差值,
总代价不能超过 maxCost。
参数:
s (str): 第一个字符串
t (str): 第二个字符串
maxCost (int): 最大允许的转换总代价
返回:
int: 满足条件的最长公共子串长度
"""
# cost 记录当前窗口的总转换代价,res 记录最大子串长度,l 是滑动窗口的左边界
cost, res, l = 0, 0, 0
# 遍历字符串 s 和 t,r 是滑动窗口的右边界
for r, (cs, ct) in enumerate(zip(s, t)):
"""
对于每一组字符对 (cs, ct):
- 计算转换代价 diff = |ord(cs) - ord(ct)|
- 将 diff 加到当前窗口的总代价 cost 上
- 如果 cost 超过 maxCost,需要移动左边界 l,减少成本
- 更新最大子串长度 res
"""
# 计算当前字符转换的代价
diff = abs(ord(cs) - ord(ct))
cost += diff
# 如果总代价超过 maxCost,移动左边界
while cost > maxCost:
# 减去左边界的转换代价
cost -= abs(ord(s[l]) - ord(t[l]))
l += 1
# 更新最大子串长度
res = max(res, r - l + 1)
return res
|
04. 水果成篮
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
# 初始化计数器、结果变量和左指针
cnt = Counter() # 用于统计窗口内每种水果的数量
res = 0 # 用于记录最大子数组的长度
l = 0 # 滑动窗口的左边界,初始为0
# 遍历数组,r是当前右边界索引,f是当前的水果类型
for r, f in enumerate(fruits):
# 如果窗口内已经有两种不同的水果,并且当前水果不在窗口内,
# 则需要移动左边界,直到窗口内少于两种不同的水果
while len(cnt) == 2 and not cnt[f]:
# 减少左边界水果的计数
cnt[fruits[l]] -= 1
# 如果某水果的计数为0,从计数器中移除
if cnt[fruits[l]] == 0:
del cnt[fruits[l]]
# 左边界向右移动
l += 1
# 将当前水果加入窗口,并增加其计数
cnt[f] += 1
# 更新结果为当前窗口大小和之前最大值中的较大者
res = max(res, r - l + 1)
# 返回最大窗口大小
return res
|
1695. 删除子数组的最大得分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Solution:
def maximumUniqueSubarray(self, nums: List[int]) -> int:
# 初始化计数器、结果变量和左指针
cnt = Counter() # 用于统计窗口内每个数字的出现次数
res = 0 # 用于记录最大子数组和
l = 0 # 滑动窗口的左边界,初始为0
current_sum = 0 # 用于记录当前窗口的和,避免每次计算sum
for r, num in enumerate(nums):
# 如果当前数字已经在窗口中(cnt[num] > 0),则需要移动左边界
while cnt[num]:
# 从计数器中移除左边界的数字,并更新当前和
cnt[nums[l]] -= 1
current_sum -= nums[l]
# 如果该数字的计数为0,从计数器中删除
if cnt[nums[l]] == 0:
del cnt[nums[l]]
l += 1 # 左边界右移
# 将当前数字加入窗口,更新计数器和当前和
cnt[num] += 1
current_sum += num
# 更新结果为当前窗口和与之前最大值中的较大者
res = max(res, current_sum)
return res
|
2958. 最多 K 个重复元素的最长子数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Solution:
def maxSubarrayLength(self, nums: List[int], k: int) -> int:
# 初始化计数器、结果变量和左指针
cnt = Counter() # 用于统计窗口内每个数字的出现次数
res = 0 # 用于记录最大子数组长度
l = 0 # 滑动窗口的左边界,初始为0
for r, num in enumerate(nums):
# 如果当前数字在窗口中出现的次数达到k次,则需要移动左边界
while cnt[num] == k:
# 减少左边界数字的计数
cnt[nums[l]] -= 1
# 如果某数字的计数为0,从计数器中移除
if cnt[nums[l]] == 0:
del cnt[nums[l]]
# 左边界右移
l += 1
# 将当前数字加入窗口,增加其计数
cnt[num] += 1
# 更新结果为当前窗口大小和之前最大值中的较大者
res = max(res, r - l + 1)
# 返回最大窗口大小
return res
|
2024. 考试的最大困扰度
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Solution:
def maxConsecutiveAnswers(self, answerKey: str, k: int) -> int:
cnt = Counter() # 初始化计数器
res = 0 # 初始化结果变量
l = 0 # 初始化左指针
for r, c in enumerate(answerKey):
cnt[c] += 1
while min(cnt['T'], cnt['F']) > k:
# 如果窗口内'T'和'F'的数量都超过k,则需要移动左边界
cnt[answerKey[l]] -= 1
l += 1
res = max(res, r - l + 1)
return res
|
1004. 最大连续1的个数 III
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Solution:
def longestOnes(self, nums: List[int], k: int) -> int:
# 初始化变量:
# zero: 记录当前窗口内0的个数
# res: 记录最大窗口大小
# l: 滑动窗口的左边界,初始为0
zero, res, l = 0, 0, 0
# 遍历数组,r为滑动窗口的右边界
for r in range(len(nums)):
# 如果nums[r]是0,zero增加1
zero += int(not nums[r])
# 如果当前窗口内0的个数超过k,需要移动左边界l
while zero > k:
# 如果nums[l]是0,zero减少1
zero -= int(not nums[l])
# 左边界向右移动一位
l += 1
# 更新结果,取当前窗口大小和之前的最大值
res = max(res, r - l + 1)
# 返回最大窗口大小
return res
|
1658. 将 x 减到 0 的最小操作数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
from typing import List
class Solution:
def minOperations(self, nums: List[int], x: int) -> int:
"""
计算最少操作次数,以使数组两端移除的元素之和等于x。
参数:
nums (List[int]): 整数数组。
x (int): 目标和。
返回:
int: 最小操作次数,如果无法实现则返回-1。
"""
# 计算目标和,即数组总和减去x
target = sum(nums) - x
# 如果目标和小于0,表示数组总和小于x,无法实现,返回-1
if target < 0:
return -1
# 如果目标和等于0,表示不需要移除任何元素,直接返回数组长度
if target == 0:
return len(nums)
# 初始化变量:
# res: 记录满足条件的窗口的最大长度
# win: 记录当前窗口的和
# l: 窗口的左边界,初始为0
# found: 标记是否找到满足条件的窗口
res, win, l, found = 0, 0, 0, False
# 遍历数组,r为窗口的右边界
for r in range(len(nums)):
# 将nums[r]加入窗口和
win += nums[r]
# 如果窗口和超过目标和,需要移动左边界
while win > target and l < r:
# 从窗口和中减去nums[l]
win -= nums[l]
# 左边界向右移动一位
l += 1
# 如果窗口和等于目标和,更新最大窗口长度
if win == target:
res = max(res, r - l + 1)
found = True
# 如果找到满足条件的窗口,返回数组长度减去最大窗口长度,否则返回-1
return len(nums) - res if found else -1
|