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

13.LeetCode 904. 水果成篮:从暴力枚举到滑动窗口的完美进阶

目录

1. 题目解析

2. 算法原理

3. 编写代码

3.1 哈希表做法

3.2 数组模拟哈希表做法(性能提升)

总结


哈喽大家好,今天我们来详细讲解 LeetCode 上的一道经典题目——904. 水果成篮。这道题本质上是一个求“最长子数组(元素种类不超过2)”的问题,非常适合用滑动窗口来解决。下面我们结合算法原理和代码实现来深入理解。

OJ链接:https://leetcode.cn/problems/fruit-into-baskets/description/

1. 题目解析

我们先来看一下题目的具体要求:

904. 水果成篮

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

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

  • 你只有两个篮子,并且每个篮子只能装单一类型​ 的水果。每个篮子能够装的水果总量没有限制。

  • 你可以选择任意一棵树开始采摘,你必须从每棵​ 树(包括开始采摘的树)上恰好摘一个水果。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘

  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组fruits,返回你可以收集的水果的最大数目

示例 1:

输入:fruits = [1,2,1]

输出:3

解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]

输出:3

解释:可以采摘 [1,2,2] 这三棵树。

如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

转化思路:

将题目转化为:找出一个最长的子数组的长度,子数组中不超过两种类型的水果。

2. 算法原理

针对这道题,我们可以采用以下两种解法:

解法一:暴力枚举 + 哈希表

  • 基本思路是枚举所有可能的子数组,利用哈希表统计每种子数组中水果的种类数,如果超过2种则跳过,否则更新最大长度。这种方法的时间复杂度较高,不推荐在大数据量下使用。

解法二:滑动窗口

滑动窗口是解决这类子数组问题的利器。

核心步骤:

  1. left = 0,right = 0(初始化左右指针)

  2. 进窗口:右指针不断向右移动,将新元素纳入窗口。

  3. 判断:检查当前窗口内水果的种类是否超过2种。

    • ① kinds 不变 -> right 不变

    • ② kinds 交小 -> right 右移

  4. 出窗口:如果种类超过2,左指针右移,将左侧元素移出窗口,直到种类恢复到2以内。

  5. 更新结果:在每一步合法状态下,更新最大水果数。

图解示意:

  • 场景1f = [1, 2, 3, 2, 2]

    • 当右指针移动到3时,窗口内有[1,2,3],种类变为3,需要收缩左边界。

  • 场景2f = [1, 2, 1, 2, 3, 2, 3, 3]

    • 同样,当遇到第三种水果3时,我们需要移动左指针left,直到窗口内只剩下两种水果。

3. 编写代码

根据上述算法原理,我们给出两种 Java 实现方式。

3.1 哈希表做法

这种方法思路直观,利用HashMap来统计窗口内水果的种类和数量。

class Solution { public int totalFruit(int[] fruits) { //用Hash表来统计窗口内水果的种类和数量 Map<Integer, Integer> hash = new HashMap<Integer, Integer>(); int ret = 0;//最大数目 for(int left = 0, right = 0; right < fruits.length; right++){ //入窗口 int in = fruits[right]; hash.put(in, hash.getOrDefault(in, 0) + 1); //判断 while(hash.size() > 2){ //出窗口 int out = fruits[left]; hash.put(out, hash.get(out) - 1); if(hash.get(out) == 0){ hash.remove(out); } left++; } //更新结果 ret = Math.max(ret, right - left + 1); } return ret; } }

注:频繁使用哈希表会导致用时较大,因为涉及到较多的哈希计算操作。

3.2 数组模拟哈希表做法(性能提升)

观察数据范围0 <= fruits[i] < fruits.length,我们可以用数组来替代哈希表,从而大幅提升时间效率。因为数组的索引访问是 O(1)的,且没有哈希冲突的开销。

class Solution { public int totalFruit(int[] fruits) { //用数组模拟Hash表来统计窗口内水果的种类和数量 int n = fruits.length; int[] hash = new int[n + 1]; int ret = 0;//最大数目 for(int left = 0, right = 0, kinds = 0; right < fruits.length; right++){ //入窗口 int in = fruits[right]; if(hash[in] == 0) kinds++; hash[in]++; //判断 while(kinds > 2){ //出窗口 int out = fruits[left]; hash[out]--; if(hash[out] == 0){ kinds--; } left++; } //更新结果 ret = Math.max(ret, right - left + 1); } return ret; } }

总结

水果成篮是典型的滑动窗口模板题。我们在处理时,关键在于维护窗口内的状态(这里是水果的种类数kinds)。当使用数组代替哈希表时,利用了题目条件对数据范围进行了优化,使得时间效率大大提升。希望大家通过这道题能熟练掌握滑动窗口的解题套路。

http://www.rkmt.cn/news/1449943.html

相关文章:

  • 大路灯护眼灯有必要吗?值得入手的护眼大路灯前十名推荐,不踩坑
  • 从Optional.orElse到Iterator.hasNext:写给Java新手的异常防御性编程手册
  • 告别盲目签约:2026年GEO优化服务商TOP5榜单 - GEO优化
  • 基于Arduino与DS18B20的温度监控报警系统设计与实现
  • 基于TSL2591与Arduino Nano的高精度DIY摄影测光表制作全攻略
  • Dify工作流完全指南:5分钟从零到一构建AI应用
  • PCB布线别再瞎画了!搞懂趋肤效应,你的高速信号质量能翻倍
  • 从‘Hello World’到数据流:用STM32CubeMX和HAL库玩转USART,实现与ESP8266的稳定通信
  • Arm Cortex-A715微架构异常解析与解决方案
  • Amass进阶玩法:除了`enum`,`intel`和`db`子命令在红队评估中怎么用?
  • 基于BD139晶体管与7812稳压的双通道LED闪烁灯设计与制作
  • 2026Q3 上海普陀家装甄选指南|老牌装企实测排行,从资质、报价、落地效果择优推荐 - 品牌优企推荐
  • Tessy工程迁移与复用实战:当.pdbx工程文件换了电脑或路径,如何快速恢复测试环境?
  • 自然语言控制电脑:UI-TARS-desktop如何重新定义人机交互范式
  • 别再手动量了!3DMAX里这个Smart Measure插件,5分钟搞定模型尺寸测量
  • Arduino与WS2812B打造儿童智能时钟:从硬件到软件的完整创客指南
  • Canvas-Editor协同编辑踩坑实录:从用户选区冲突到数据同步的那些‘坑’
  • 不只是主题美化:用Oh My Zsh插件打造你的命令行‘外挂’工作流(附zsh-autosuggestions高阶配置)
  • 基于Arduino的智能泡茶机DIY:从硬件选型到状态机编程全解析
  • 别再死记硬背了!用这5个钢琴/吉他实战片段,彻底搞懂乐理里的‘波音’怎么弹
  • CAD 2021新手必看:从安装到画第一张图的完整设置流程(含经典模式切换与关键选项解析)
  • 从一道综合题出发:实战绕过Canary+PIE+ASLR全保护(含Libc计算)
  • 从Modbus到Profinet:给S7-1200 PLC通讯协议选型画张“地图”(含RS485接线避坑)
  • 别再手动调滤波器了!用Matlab快速验证Farrow插值性能,为FPGA设计铺路
  • 两大技巧:安卓手机批量发短信且不创建群聊
  • 2026 郑州新高一学校择校全攻略:排名、口碑、班型、区域推荐,到底怎么选 - GrowthUME
  • 别再被AI新名词吓到!Smaller.孔带你建立上帝视角,一张图看懂AI智能体生态全布局
  • 告别裸奔AssetBundle!手把手教你打造资源加密加载管线(Unity 2022+)
  • 2026 北京上门收酒机构排名深度解析:综合实力 TOP5 权威榜单 - 品牌排行榜单
  • 告别NeRF的漫长等待:用3D Gaussian Splatting在RTX 4090上实现实时新视图合成