问题描述
小U正在探访一座农场,农场的果树排成一列,用整数数组 fruits 表示,每个元素 fruits[i] 是第 i 棵树上的水果种类。小U有两个篮子,每个篮子只能装一种类型的水果,而且每个篮子可以装无限量的水果。小U从任意一棵树开始,必须从每棵树上恰好采摘一个水果,并且只能装入符合篮子中水果类型的果实。如果某棵树上的水果类型不符合篮子中的水果类型,则必须停止采摘。请你帮助小U计算他最多可以采摘多少个水果。例如:当 fruits = [1,2,3,2,2] 时,小U最多可以采摘的树是从第2棵开始,采摘到最后的 4 棵树,结果为 [2,3,2,2]。
代码原理
代码使用了滑动窗口算法来解决这个问题。滑动窗口算法是一种常用的双指针技术,用于解决数组和字符串相关的问题。
滑动窗口算法的工作原理
-
扩展窗口:
- 通过移动
end指针,将新的水果加入窗口,并更新fruit_count。 - 如果窗口中水果类型不超过两种,继续扩展窗口。
- 通过移动
-
收缩窗口:
- 如果窗口中水果类型超过两种,移动
start指针,收缩窗口,直到窗口中只包含两种水果类型。 - 在收缩窗口的过程中,更新
fruit_count,减少或移除不再在窗口中的水果。
- 如果窗口中水果类型超过两种,移动
-
更新最大值:
- 在每次扩展或收缩窗口后,计算当前窗口的长度(
end - start + 1),并更新max_fruits。
- 在每次扩展或收缩窗口后,计算当前窗口的长度(
代码思路
-
初始化变量:
max_fruits:用于记录最大采摘数量,初始值为0。start:窗口的起始位置,初始值为0。fruit_count:一个字典,用于记录当前窗口中每种水果的数量。
-
遍历数组:
for end in range(len(fruits)):遍历数组,end表示窗口的结束位置。fruit = fruits[end]:获取当前水果。if fruit in fruit_count:如果当前水果已经在字典中,增加其数量。else:如果当前水果不在字典中,将其添加到字典并设置数量为1。
-
收缩窗口:
while len(fruit_count) > 2:如果窗口中水果类型超过两种,收缩窗口。start_fruit = fruits[start]:获取窗口起始位置的水果。fruit_count[start_fruit] -= 1:减少该水果的数量。if fruit_count[start_fruit] == 0:如果该水果数量为0,从字典中移除。start += 1:移动窗口的起始位置。
-
更新最大采摘数量:
max_fruits = max(max_fruits, end - start + 1):更新最大采摘数量,当前窗口的长度为end - start + 1。
-
返回最大采摘数量:
return max_fruits:返回最大采摘数量。
代码
def solution(fruits: list) -> int:
max_fruits = 0
start = 0
fruit_count = {}
for end in range(len(fruits)):
fruit = fruits[end]
if fruit in fruit_count:
fruit_count[fruit] += 1
else:
fruit_count[fruit] = 1
while len(fruit_count) > 2:
start_fruit = fruits[start]
fruit_count[start_fruit] -= 1
if fruit_count[start_fruit] == 0:
del fruit_count[start_fruit]
start += 1
max_fruits = max(max_fruits, end - start + 1)
return max_fruits`
`