LeetCode 904. 水果成篮

题目链接

904. 水果成篮

题目描述

在一排果树上采摘水果,每棵树结一种水果(用整数表示种类)。你只有两个篮子,每个篮子只能装一种水果。求最多能采摘的水果数量,要求采摘的水果种类不能超过两种。

解法分析:滑动窗口法

核心思路

使用滑动窗口技术维护一个区间,确保区间内最多包含2种水果。当区间内水果种类超过2种时,移动左指针缩小窗口,直到满足条件。窗口的最大长度即为能采摘的最多水果数量。

代码实现

class Solution:
    def totalFruit(self, fruits: List[int]) -> int:
        m = {}  # 记录窗口内水果种类及其数量
        l = ans = 0  # 左指针、最大水果数量
        for i in range(len(fruits)):
            # 更新当前水果的数量
            m[fruits[i]] = m.get(fruits[i], 0) + 1
            
            # 当水果种类超过2种时,收缩左边界
            while len(m) > 2:
                m[fruits[l]] -= 1
                if m[fruits[l]] == 0:
                    del m[fruits[l]]  # 移除数量为0的水果种类
                l += 1  # 左指针右移
            
            # 更新最大水果数量(窗口长度)
            ans = max(ans, i - l + 1)
        
        return ans

代码解析

  1. 初始化

    • m:字典,用于记录当前窗口内每种水果的数量
    • l:滑动窗口的左指针,初始位置为0
    • ans:记录能采摘的最大水果数量,初始为0
  2. 遍历果树

    • 右指针i从0开始遍历每棵果树
    • m[fruits[i]] = m.get(fruits[i], 0) + 1:将当前果树的水果加入窗口,并更新其数量
    • 使用dict.get(key, default)方法避免键不存在时的错误
  3. 调整窗口

    • len(m) > 2时,说明窗口内水果种类超过2种
    • m[fruits[l]] -= 1:减少左指针处水果的数量
    • 若水果数量变为0,则从字典中删除该水果种类
    • l += 1:左指针右移,缩小窗口范围,直到窗口内水果种类≤2种
  4. 更新结果

    • ans = max(ans, i - l + 1):计算当前窗口长度并更新最大水果数量
    • 窗口长度为i - l + 1,表示从左指针到右指针的果树数量

关键逻辑图示

以输入fruits = [1,2,3,2,2]为例:

  1. i=0,水果1

    • m={1:1},种类数1≤2,窗口长度1,ans=1
  2. i=1,水果2

    • m={1:1, 2:1},种类数2≤2,窗口长度2,ans=2
  3. i=2,水果3

    • m={1:1, 2:1, 3:1},种类数3>2,进入收缩:

      • m[1] -=1 → m[1]=0,删除1,l=1
    • m={2:1, 3:1},种类数2≤2,窗口长度2-1+1=2,ans=2
  4. i=3,水果2

    • m={2:2, 3:1},种类数2≤2,窗口长度3-1+1=3,ans=3
  5. i=4,水果2

    • m={2:3, 3:1},种类数2≤2,窗口长度4-1+1=4,ans=4
  6. 最终返回4,即最多能采摘4个水果

复杂度分析

  • 时间复杂度:O(n),其中n是果树的数量。每个果树最多被左右指针各访问一次,总操作次数不超过2n。
  • 空间复杂度:O(1),字典中最多存储2种水果的信息,空间使用与输入规模无关。

总结

该解法通过滑动窗口和哈希表高效解决了水果成篮问题,核心在于维护窗口内水果种类不超过2种。当种类超过时收缩左边界,确保窗口有效性。这种方法是解决"最多包含k种元素"的子数组问题的经典解法,时间和空间复杂度均为最优。

滑动窗口的关键在于:

  1. 定义窗口的左右指针
  2. 维护窗口内的状态(本题中是水果种类数)
  3. 当状态不满足条件时调整窗口边界
  4. 实时更新最优解

这种思路可以扩展到类似问题,如"最多包含k个不同字符的最长子串"等,具有很强的通用性。

你可能感兴趣的:(滑动窗口python)