344. 农场采摘水果问题
问题描述
小U正在探访一座农场,农场的果树排成一列,用整数数组 fruits 表示,每个元素 fruits[i] 是第 i 棵树上的水果种类。
小U有两个篮子,每个篮子只能装一种类型的水果,而且每个篮子可以装无限量的水果。小U从任意一棵树开始,必须从每棵树上恰好采摘一个水果,并且只能装入符合篮子中水果类型的果实。如果某棵树上的水果类型不符合篮子中的水果类型,则必须停止采摘。
请你帮助小U计算他最多可以采摘多少个水果。
例如:当 fruits = [1,2,3,2,2] 时,小U最多可以采摘的树是从第2棵开始,采摘到最后的 4 棵树,结果为 [2,3,2,2]。
测试样例
样例1:
输入:
fruits = [1,2,1,2]
输出:4
样例2:
输入:
fruits = [2,0,1,2,2]
输出:3
样例3:
输入:
fruits = [1,2,3,2,2,4]
输出:4
思路:
滑动窗口问题。我们需要找到一个连续的子数组,该子数组中最多包含两种不同的水果类型,并且求出这个子数组的最大长度。使用滑动窗口的技巧,使用字典来记录窗口内每种水果的数量,通过不断扩大窗口并调整窗口的起始位置来解决问题。在动态维护窗口的过程中记录窗口最大值,维护结束后返回。
代码实现:
def solution(fruits: list) -> int:
# 字典,用于存储窗口内每种水果的数量
fruit_count = {}
# 左指针
left = 0
# 最大水果数
max_fruits = 0
# 遍历水果数组
for right in range(len(fruits)):
# 当前水果类型
fruit = fruits[right]
# 更新水果的数量
if fruit in fruit_count:
fruit_count[fruit] += 1
else:
fruit_count[fruit] = 1
# 如果字典中水果种类超过两种,缩小窗口
while len(fruit_count) > 2:
left_fruit = fruits[left]
fruit_count[left_fruit] -= 1
if fruit_count[left_fruit] == 0:
del fruit_count[left_fruit]
left += 1
# 更新最大水果数
max_fruits = max(max_fruits, right - left + 1)
return max_fruits
复杂度分析:
- 时间复杂度:
O(n),其中n是水果树的数量。每个元素被访问的次数最多是 2 次(一次通过右指针,另一次通过左指针),因此总时间复杂度是线性的。 - 空间复杂度:
O(k),其中k是窗口内水果种类的数量,最坏情况下为 2(因为我们最多只关注两种水果)。