当前位置: 首页 > news >正文

滑动窗口题目:水果成篮

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:水果成篮

出处:904. 水果成篮

难度

5 级

题目描述

要求

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits\texttt{fruits}fruits 表示,其中 fruits[i]\texttt{fruits[i]}fruits[i] 是第 i\texttt{i}i 棵树上的水果种类

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求收集水果:

  • 你只有两个篮子,并且每个篮子只能装单一类型的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始收集,向右移动的过程中,你必须从每棵树(包括开始收集的树)上恰好摘一个水果。收集的水果应当符合一个篮子中的水果类型。
  • 一旦你走到某棵树前,但水果不符合任何篮子中的水果类型,那么就必须停止收集。

给定一个整数数组 fruits\texttt{fruits}fruits,返回你可以收集的水果的最大数目。

示例

示例 1:

输入:fruits=[1,2,1]\texttt{fruits = [1,2,1]}fruits = [1,2,1]
输出:3\texttt{3}3
解释:可以收集全部 3\texttt{3}3 棵树。

示例 2:

输入:fruits=[0,1,2,2]\texttt{fruits = [0,1,2,2]}fruits = [0,1,2,2]
输出:3\texttt{3}3
解释:可以收集 [1,2,2]\texttt{[1,2,2]}[1,2,2] 这三棵树。
如果从第一棵树开始收集,则只能收集 [0,1]\texttt{[0,1]}[0,1] 这两棵树。

示例 3:

输入:fruits=[1,2,3,2,2]\texttt{fruits = [1,2,3,2,2]}fruits = [1,2,3,2,2]
输出:4\texttt{4}4
解释:可以收集 [2,3,2,2]\texttt{[2,3,2,2]}[2,3,2,2] 这四棵树。
如果从第一棵树开始收集,则只能收集 [1,2]\texttt{[1,2]}[1,2] 这两棵树。

数据范围

  • 1≤fruits.length≤105\texttt{1} \le \texttt{fruits.length} \le \texttt{10}^\texttt{5}1fruits.length105
  • 0≤fruits[i]<fruits.length\texttt{0} \le \texttt{fruits[i]} < \texttt{fruits.length}0fruits[i]<fruits.length

解法

思路和算法

根据收集水果的要求,收集的水果必须是数组 fruits\textit{fruits}fruits 中的一个子数组,且子数组中至多包含 222 个不同元素。由于每棵树必须摘一个水果,因此收集的水果数目等于子数组的长度。为了得到收集的水果的最大数目,应得到符合要求的最长子数组。

根据上述分析,问题转化成在数组 fruits\textit{fruits}fruits 中寻找至多包含 222 个不同元素的最长子数组。

考虑数组 fruits\textit{fruits}fruits 的两个不同下标 end1\textit{end}_1end1end2\textit{end}_2end2,其中 end1<end2\textit{end}_1 < \textit{end}_2end1<end2,分别以这两个下标作为结束下标,寻找至多包含 222 个不同元素的最长子数组,将这两个最长子数组的开始下标分别记为 start1\textit{start}_1start1start2\textit{start}_2start2,则必有 start1≤start2\textit{start}_1 \le \textit{start}_2start1start2(否则对于任意 start2≤start3<start1\textit{start}_2 \le \textit{start}_3 < \textit{start}_1start2start3<start1,下标范围 [start3,end1][\textit{start}_3, \textit{end}_1][start3,end1] 的子数组至多包含 222 个不同元素,且长度大于下标范围 [start1,end1][\textit{start}_1, \textit{end}_1][start1,end1] 的子数组)。

因此,可以使用变长滑动窗口寻找数组 fruits\textit{fruits}fruits 中的至多包含 222 个不同元素的最长子数组。用 [start,end][\textit{start}, \textit{end}][start,end] 表示滑动窗口,初始时 start=end=0\textit{start} = \textit{end} = 0start=end=0。将滑动窗口的右端点 end\textit{end}end 向右移动,移动过程中维护滑动窗口的左端点 start\textit{start}start,确保滑动窗口中至多包含 222 个不同元素。

使用哈希表记录滑动窗口中的每个元素的出现次数。对于每个右端点 end\textit{end}end,执行如下操作。

  1. fruits[end]\textit{fruits}[\textit{end}]fruits[end] 在哈希表中的次数加 111

  2. 如果哈希表中的元素个数大于 222,则将 fruits[start]\textit{fruits}[\textit{start}]fruits[start] 在哈希表中的次数减 111,如果 fruits[start]\textit{fruits}[\textit{start}]fruits[start] 在哈希表中的次数变成 000 则将 fruits[start]\textit{fruits}[\textit{start}]fruits[start] 从哈希表中删除,然后将 start\textit{start}start 向右移动一位,重复该操作直到哈希表中的元素个数小于等于 222

  3. 当前滑动窗口 [start,end][\textit{start}, \textit{end}][start,end] 中的子数组为至多包含 222 个不同元素的子数组,其长度为 end−start+1\textit{end} - \textit{start} + 1endstart+1,使用当前子数组的长度更新子数组的最大长度。

遍历结束之后,可以得到数组 fruits\textit{fruits}fruits 中的至多包含 222 个不同元素的子数组的最大长度,即收集的水果的最大数目。

实现方面,由于数组 fruits\textit{fruits}fruits 中的所有元素都是小于数组长度的非负整数,因此可以创建一个与数组 fruits\textit{fruits}fruits 等长的数组 counts\textit{counts}counts 代替哈希表,当数组 counts\textit{counts}counts 中的一个元素值从 000 变成 111 时哈希表中的元素个数增加 111 个,当数组 counts\textit{counts}counts 中的一个元素值从 111 变成 000 时哈希表中的元素个数减少 111 个。

代码

class Solution {public int totalFruit(int[] fruits) {int length = fruits.length;int[] counts = new int[length];int maxFruits = 0;int baskets = 0;int start = 0, end = 0;while (end < length) {int type = fruits[end];counts[type]++;if (counts[type] == 1) {baskets++;}while (baskets > 2) {int prev = fruits[start];counts[prev]--;if (counts[prev] == 0) {baskets--;}start++;}maxFruits = Math.max(maxFruits, end - start + 1);end++;}return maxFruits;}
}

复杂度分析

  • 时间复杂度:O(n)O(n)O(n),其中 nnn 是数组 fruits\textit{fruits}fruits 的长度。滑动窗口的左右端点最多各遍历数组 fruits\textit{fruits}fruits 一次。

  • 空间复杂度:O(n)O(n)O(n),其中 nnn 是数组 fruits\textit{fruits}fruits 的长度。空间复杂度主要取决于哈希表,哈希表中的不同元素个数不超过数组 fruits\textit{fruits}fruits 的长度。

http://www.xdnf.cn/news/1455625.html

相关文章:

  • C 盘清理技巧分享:释放磁盘空间,提升系统性能
  • ArcGIS学习-15 实战-建设用地适宜性评价
  • 适应新环境:Trae编辑器下的IDEA快捷键定制
  • 解密大语言模型推理:Prompt Processing 的内存管理与计算优化
  • C++语言编程规范-常量
  • 既“强悍”又“灵活”,部署在用户身边,将直播延迟压缩至毫秒级
  • Kafka 学习教程:从基础概念到实践操作
  • 分析流程自动优化!Fabarta个人专属智能体「数据分析」新功能介绍
  • 打工人日报#20250904
  • docker中的mysql变更宿主机映射端口
  • 以StarRocks为例讲解MPP架构和列式存储
  • vscode launch.json 中使用 cmake tools 扩展的命令获取可执行文件目标文件名
  • 设计师的私有化远程协作解决方案,是OpenUI与cpolar组合的标配功能
  • 目标检测系列-Yolov5下载及运行
  • 深度学习下的单阶段通用目标检测算法研究综述2.0
  • Java全栈工程师的实战面试:从Vue到Spring Boot的技术旅程
  • PSU电源原理
  • 双指针扫描使用简述
  • 【AI论文】面向大语言模型(LLMs)的具身强化学习全景图:一项调研综述
  • 新闻稿的发布平台有哪些?选对渠道让发稿效果事半功倍!
  • 移远EC200A OpenCPU笔记
  • 一文吃透同态滤波算法!从原理到 MATLAB 实战,小白也能懂
  • 解析PE文件的导入表和导出表
  • 准确率可达99%!注意力机制+UNet,A会轻松收割!
  • 20250904的学习笔记
  • HTML + CSS 创建图片倒影的 5 种方法
  • 大数据毕业设计选题推荐-基于大数据的儿童出生体重和妊娠期数据可视化分析系统-Hadoop-Spark-数据可视化-BigData
  • 加密货币武器化:恶意npm包利用以太坊智能合约实现隐蔽通信
  • 性能堪比claude sonnet4,免费无限使用!claude code+魔搭GLM4.5在ubuntu上安装完整流程
  • Cadence OrCAD Capture绘制复用管脚封装的方法图文教程