刷题记录 344. 农场采摘水果问题

100 阅读2分钟

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(因为我们最多只关注两种水果)。