农场采摘水果问题 双指针之滑动窗口 | 豆包MarsCode AI 刷题

69 阅读3分钟

问题描述

小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

问题分析

首先我们确定,它让我们返回的并不是出现次数最多的两个种类的和,而是在数组的某一段中,若该段仅最多有两个种类,则取这种数组长度的最大值。

对于这种求数组某一段的问题,我们可以使用滑动窗口的方法来解决。

具体地说,我们可以遍历这个数组中的每个右端点,然后判断以该点为右端点的子数组的最大长度,那么我们在遍历到该点的时候会出现两种情况,一个情况是当前采摘水果的种类还小于等于2,这个时候我们不仅可以更新答案的最大值,还可以直接开始遍历下一个点。第二个情况是当前采摘水果的种类已经大于二了,那么这个时候我们就需要移动这个子数组的左端点,直到这个子数组中仅有两个种类的水果。

对于当前子数组中存在的水果种类以及数量,可以用我之前文章中提到的Counter来实现计数。

代码实现

-   时间复杂度O(n)
-   空间复杂度O(1)

本题总结

数据结构选择

  • Counter: 用于记录当前窗口内每种水果的数量。
  • 双指针: 用于维护一个滑动窗口,确保窗口内的水果种类不超过两种。

算法步骤

  1. 初始化:

    • 使用 Counter 记录当前窗口内每种水果的数量。
    • 初始化 left 指针为窗口的左边界,ans 记录最大采摘数量。
  2. 遍历数组:

    • 使用 right 指针遍历数组,每次将当前水果加入 Counter
    • 如果 Counter 中的水果种类超过两种,则移动 left 指针,直到窗口内的水果种类不超过两种。
  3. 更新最大值:

    • 每次移动 right 指针后,更新 ans 为当前窗口长度(right - left + 1)的最大值。
  4. 返回结果:

    • 遍历结束后,返回 ans,即小U最多可以采摘的水果数量。

双指针浅析

双指针是一种常用的算法技巧,通常用于解决数组或链表相关的问题。双指针通过在数据结构中使用两个指针,分别从不同的位置开始移动,以达到某种目标或满足某种条件。

双指针的优点

  • 时间复杂度低: 通常为 O(n),因为两个指针各自遍历一次数组或链表。
  • 空间复杂度低: 通常为 O(1),因为只需要常数级别的额外空间。

因此,双指针技巧在解决数组和链表问题时非常有效,能够显著提高算法的效率。