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

L48.【LeetCode题解】904. 水果成篮

目录

1.题目

2.分析

方法1:暴力枚举

方法2:暴力解法的优化:滑动窗口

代码

方法3:优化方法2:使用数组充当哈希表

方法4:四个变量分别充当篮子和篮子中水果的个数(最快!!!)

代码

容易忽略的点


1.题目

https://leetcode.cn/problems/fruit-into-baskets/

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

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

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

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

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

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

示例 3:

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

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

提示:

  • 1 <= fruits.length <= 10^5
  • 0 <= fruits[i] < fruits.length

2.分析

需要使用set来统计[left,right]之间水果的种类数

方法1:暴力枚举

class Solution {
public:int totalFruit(vector<int>& fruits) {int left=0,right=0,ret=0;for (;left<fruits.size();left++){set<int> mp;for (right=left;right<fruits.size();right++){mp.insert(fruits[right]);if (mp.size()>2)break;}       ret=max(ret,right-left);}return ret;}
};

提交结果:超时

方法2:暴力解法的优化:滑动窗口

right不用每次都从left开始枚举,以这个为例:[1,2,1,2,3,2,3,3]

当mp.size()>2时,

left只需要向前移动,直到mp.size()\leqslant2时停止移动,能减少大量无用的循环,提高运行速度

使用存储双关键字类型的map<int,int>,第一个关键字存储类型,第二个关键字存储每类的水果的个数

可以先mp[fruits[right]]++(进窗口),看看mp.size()有没有超过2,如果超过,使mp[fruits[left++]]--(出窗口),如果发现减到0了,就erase(注:erase直接删除掉节点的所有信息, 不是让mp[x]置为0)

最后更新结果:ret=max(ret,right-left+1);

代码

class Solution {
public:int totalFruit(vector<int>& fruits) {map<int,int> mp;int left=0,right=0,ret=0; for (;right<fruits.size();right++){mp[fruits[right]]++;while (mp.size()==3){mp[fruits[left++]]--;if (mp[fruits[left-1]]==0)mp.erase(fruits[left-1]);}ret=max(ret,right-left+1);}return ret;}
};

提交结果:

当然也可以使用unordered_map解决:

但无论是map还是unordered_map对mp多次插入和删除比较耗时,时间复杂度较高,可以使用方法3:数组充当哈希表

方法3:优化方法2:使用数组充当哈希表

要多用一个变量kind来存储水果种类的数量,因为1 <= fruits.length <= 10^5 使用哈希数组hash[100001]来存储,哈希数组的特点正好符合对双关键字的要求,对于种类为x的水果,其个数为hash[x]

kind++的条件:hash[fruit[right]]从0变成1

kind--的条件:hash[fruit[right]]从1变成0

class Solution {
public:int totalFruit(vector<int>& fruits) {int hash[100001]={0};int left=0,right=0,ret=0,kind=0; for (;right<fruits.size();right++){hash[fruits[right]]++;if (hash[fruits[right]]==1)kind++;while (kind==3){hash[fruits[left++]]--;if (hash[fruits[left-1]]==0)kind--;}ret=max(ret,right-left+1);}return ret;}
};

提交结果:

方法4:四个变量分别充当篮子和篮子中水果的个数(最快!!!)

bkt1存储篮子1的水果种类数,篮子1的水果个数为bkt1_num(bkt为basket的简写)

bkt2存储篮子2的水果种类数,篮子1的水果个数为bkt2_num

代码

class Solution {
public:int totalFruit(vector<int>& fruits){int bkt1 = -1, bkt2 = -1, bkt1_num = 0, bkt2_num = 0;int left = 0, right = 0, ret = 0;for (; right < fruits.size(); right++){if (bkt1 == -1){bkt1 = fruits[right];bkt1_num++;}else if (bkt2 == -1&&fruits[right]!=bkt1){bkt2 = fruits[right];bkt2_num++;}else{if (fruits[right] == bkt1)bkt1_num++;else if (fruits[right] == bkt2)bkt2_num++;else//如果出现第三种水果{while (1){if (fruits[left] == bkt1)bkt1_num--;elsebkt2_num--;left++;if (bkt1_num == 0){bkt1 = fruits[right];bkt1_num++;break;}if (bkt2_num == 0){bkt2 = fruits[right];bkt2_num++;break;}}}}ret = max(ret, right - left + 1);}return ret;}
};

容易忽略的点

else if (bkt2 == -1&&fruits[right]!=bkt1)的fruits[right]!=bkt1不可以省,否则将无法通过[0,0,1,1]测试用例

提交结果:

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

相关文章:

  • 《 指针变量的创建:初探内存世界的钥匙》
  • 【技巧】如何把win10 wsl的安装目录从c盘迁移到d盘
  • 【Gradio】helloworld程序
  • 嵌入式开发学习(第二阶段 C语言基础)
  • 随笔-近况
  • 插槽、生命周期
  • QWindowkit 实现无边框,阴影支持系统边栏缩放等功能
  • 深入理解C/C++内存管理:从基础到高级优化实践
  • 2025年数维杯C题数据收集方式分享
  • Vue3 路由配置与跳转传参完整指南
  • 二分系列题
  • 【PhysUnits】3.3 SI 基础量纲单位(units/base.rs)
  • 深入理解 JavaScript 对象与属性控制
  • 少儿编程机构用的教务系统
  • AT9880B北斗单模卫星定位SOC芯片
  • 问题五、扩展模板生成器
  • 【NextPilot日志移植】Logger::run()主循环解析
  • 图像配准简单概述
  • 日常知识点之随手问题整理(思考单播,组播,广播哪个更省带宽)
  • MySQL初阶:数据库约束和表的设计
  • Linux基础(关于进程相关命令)
  • WPDRRC 模型:构建动态闭环的信息安全防御体系
  • 深度学习系统学习系列【8】之设计卷积神经网络架构(Pytorch版本)
  • RHCSA Linux系统软件管理和进程管理
  • flowable-适配其他类型数据库,不修改源码解决方案
  • 位运算(二进制中1的个数)
  • uniapp自定义导航栏搭配插槽
  • Linux的进程与线程
  • 笔记,麦克风的灵敏度
  • Jedis高版本的JedisPoolConfig没有maxActive和maxWait