【滑动窗口】水果成篮

news2025/1/19 11:13:27

水果成篮

904. 水果成篮 - 力扣(LeetCode)

文章目录

  • 水果成篮
    • 题目描述
      • 问题转化
    • 算法原理
      • 解法一
      • 解法二
    • 代码编写
      • C++代码:
        • 使用容器
        • 数组模拟哈希表
      • Java代码
        • 使用容器
        • 数组模拟哈希表

题目描述

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 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 <= 105
  • 0 <= fruits[i] < fruits.length

问题转化

找出一个最长的子数组的长度。子数组的要求就是子数组中不超过两种类型的水果

算法原理

解法一

暴力枚举 + 哈希

用哈希表的作用就是可以判断水果的类型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用两层循环来枚举所有可能的子数组,并计算每个子数组中水果的种类数。

对于每个子数组,我们可以使用一个哈希表来记录水果的种类和数量。

在内层循环中,我们遍历当前子数组并更新哈希表。如果哈希表中记录的水果种类数超过2,我们就停止内层循环。

在每次内层循环结束后,我们比较当前子数组的长度与之前的最大长度,更新最大长度的值。

// 暴力解法
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int ret = 0; // 结果
        int n = fruits.size();
        for(int i = 0; i < n; i++)
        {
            unordered_map<int, int>hash; // 哈希
            int kinds = 0; // 水果的类型
            for(int j = i ; j < n ; j ++)
            {
                hash[fruits[j]]++;
                if(hash[fruits[j]] == 1 ) kinds++;
                
                if(kinds >2) break;

                ret = max(ret, j - i + 1);
            }
        }
        return ret;
    }
};

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

额…

解法二

优化:滑动窗口

我们的前提就是:让滑动窗口满足窗口内的水果只有两种

算法流程:

  1. 初始化一个哈希表hash或者一个数组来统计窗口内的元素
  2. 初始化变量,定义左右指针right、left = 0,记录结果的变量ret = 0
  3. right < 数组长度,一直循环
    • right遍历过的数组元素放入哈希表中
    • 判断
      • 如果哈希表> 2
        • 将左侧元素滑出窗口,并且哈希表中将该元素的次数-1
        • 如果这个次数-1的元素之后变成0,那么就将该元素从哈希表中删除
        • 持续重复以上的操作,直到哈希表的大小 =2
      • 更新结果ret
      • right++,让下一个元素进入窗口
  4. 循环结束之后,ret就是最后的结果

代码编写

C++代码:

使用容器
// 使用容器
class Solution {
public:
    int totalFruit(vector<int>& f) {
        unordered_map<int, int>hash; // 统计窗口内出现了多少种水果
        int ret = 0; // 结果
        for(int left = 0, right = 0; right < f.size(); right ++)
        {
            hash[f[right]]++; // 进窗口
            while(hash.size() > 2) // 判断
            {
                // 出窗口
                hash[f[left]]--;
                if(hash[f[left]] == 0)
                    hash.erase(f[left]);
                left++;
            }
            // 更新结果
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数组模拟哈希表
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int hash[100001] = {0}; // 数组模拟哈希表

        int ret = 0;
        int n = fruits.size();
        for(int left = 0, right = 0, kinds = 0; right < n; right++)
        {
            if(hash[fruits[right]] == 0) kinds++; // 维护水果的种类
            hash[fruits[right]]++; // 进窗口

            while(kinds > 2) // 判断
            {
                // 出窗口
                hash[fruits[left]]--;
                if(hash[fruits[left]] == 0) kinds--;
                left++;
            }
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Java代码

使用容器
class Solution {
    public int totalFruit(int[] fruits) {
        Map<Integer, Integer>hash = new HashMap<Integer, Integer>(); // 容器统计窗口内水果的种类
        int ret = 0;
        int n = fruits.length;

        for(int right = 0, left = 0; right < n; right ++)
        {
            int in = fruits[right]; // in 是进窗口的元素
            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 + 1 - left);
        }
        return ret;
    }
}

解释一下代码中的部分代码:

hash.put(in, hash.getOrDefault(in, 0) + 1);

在这个代码片段中,hash 是一个哈希表对象,in 是作为键的水果类型,hash.getOrDefault(in, 0) 是获取键 in 对应的值,如果该键不存在则返回默认值 0。然后,hash.getOrDefault(in, 0) + 1 将该键对应的值加1。最后,hash.put(in, hash.getOrDefault(in, 0) + 1) 将更新后的键值对存储到哈希表中。

hash.put(out, hash.get(out) - 1);

hash.get(out) 是获取键 out 对应的值,然后将其减1。最后,hash.put(out, hash.get(out) - 1) 将更新后的键值对存储到哈希表中。

hash.remove(out);

remove就是删除元素

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数组模拟哈希表
class Solution {
    public int totalFruit(int[] fruits) {
        int ret = 0; // 结果
        int n = fruits.length;
        int[] hash = new int[n + 1]; // 保险起见,开 n + 1 个空间
        for(int right = 0, left = 0, kinds = 0; right < n; 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 + 1 - left);
        }
        return ret;
    }
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1280460.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 队列的说明 1.1 队列的几种常用操作 2.0 使用链表实现队列说明 2.1 链表实现队列 2.2 链表实现队列 - 入栈操作 2.3 链表实现队列 - 出栈操作 2.4 链表实现队列 …

养身馆推拿会员管理系统,佳易王推拿会员管理软件短信设置教程

养身馆推拿会员管理系统&#xff0c;佳易王推拿会员管理软件短信设置教程 一、佳易王会员管理软件大众版 部分功能简介&#xff1a; 1、会员信息登记 &#xff1a;可以直接使用手机号登记&#xff0c;也可以使用实体卡片&#xff0c;推荐用手机号即可。 2、会员卡类型 &…

【每日一题】可获得的最大点数

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;滑动窗口方法二&#xff1a;前缀和 写在最后 Tag 【滑动窗口】【前缀和】【数组】【2023-12-03】 题目来源 1423. 可获得的最大点数 题目解读 在一排卡牌中拿出 k 张卡牌&#xff0c;每次必须从这一排卡牌的开头或者…

运维02:Linux

Linux安装 VMWare安装&#xff1a;夸克网盘分享&#xff08;提取码&#xff1a;refg&#xff09; CentOS安装&#xff1a;Index of /centos/7.9.2009/isos/x86_64/ Xshell安装&#xff1a;百度网盘 请输入提取码&#xff08;提取码&#xff1a;juau&#xff09; 环境准备 1、…

Pikachu(三)

RCE(remote command/code execute)概述 RCE漏洞&#xff0c;可以让攻击者直接向后台服务器远程注入操作系统命令或者代码&#xff0c;从而控制后台系统。 远程系统命令执行 一般出现这种漏洞&#xff0c;是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口 比如我…

Cmkae外部依赖管理

文章目录 一、cmake依赖管理介绍二、源码依管理1. FetchContent与find_package进行集成 2. CPM3. git submodule附加&#xff1a; address_sanitizer 和 undefined sanitizer 一、cmake依赖管理介绍 CMake 是跨平台的构建系统&#xff0c;支持 C/C、Objective-C、Fortran 等多种…

C++基础 -36- 模板之模板函数

模板函数格式 template <class T> void allexchange(T a,T b) {T c;c*a;*a*b;*bc; }模板函数可以增强函数的通用性 举例说明&#xff0c;使用一个模板函数实现了两个的函数的功能 #include "iostream"using namespace std;void myexchangeint(int* a,int* …

Grafana部署与Zabbix集成,搭建开源IT监控平台

Grafana部署与Zabbix集成 目前在一家公司主要是网络、运维、IT支持&#xff0c;每次需要检查服务器状态都是需要手动登录系统进行查看&#xff0c;因此想着部署一套监控系统&#xff0c;功能上需要实现监控、可视化、告警等。由于预算没有&#xff0c;服务器资源倒是有空闲的&a…

【hacker送书活动第7期】Python网络爬虫入门到实战

第7期图书推荐 内容简介作者简介大咖推荐图书目录概述参与方式 内容简介 本书介绍了Python3网络爬虫的常见技术。首先介绍了网页的基础知识&#xff0c;然后介绍了urllib、Requests请求库以及XPath、Beautiful Soup等解析库&#xff0c;接着介绍了selenium对动态网站的爬取和S…

电容和电感

一、电感 1&#xff09;图片 2&#xff09;作用 a&#xff09;储存容量 例如dcdc转换器的原理,将一个电压值转换成另外一个电压值 b&#xff09;选择信号 比如空气中弥漫着很多信号&#xff0c;我们应该怎么选取我们所需要的信号。 电感和电容可以看成一个电阻&#xff0c;当电…

Redis ziplist源码解析

area |<---- ziplist header ---->|<----------- entries ------------->|<-end->|size 4 bytes 4 bytes 2 bytes ? ? ? ? 1 byte--------------------------------------------------------------- comp…

MySQL进阶部分

存储引擎 MySQL体系结构图&#xff1a; 连接层&#xff1a; 最上层是一些客户端连接服务&#xff0c;主要完成一些类似于连接处理 &#xff0c;授权认证及相关的安全方案。服务器也会为安全接入的每个用户端验证它所具有的操作权限。 服务层&#xff1a; 第二层架构主要完成大…

数据科学:Matplotlib、Seaborn笔记

数据科学&#xff1a;Numpy、Pandas、Matplotlib、Seaborn 三、Matplotlib1.Matplotlib subplots函数2.tight_layout()函数3.Matplotlib grid()设置网格格式4.fill_between()函数示例设置x轴为时间刻度热力图 四、Seaborn1.set2.seaborn.scatterplot 参考 数据科学&#xff1a;…

github打不开,全网最简单解决方法,没有之一

下载watt toolkit&#xff0c; 选择‘github’&#xff0c;点击‘一键加速’&#xff0c; 具体步骤如下&#xff1a;去电脑微软商店下载watt toolkit&#xff0c;或者直接打开网址https://apps.microsoft.com/detail/9MTCFHS560NG?hlen-us&glUS 如图&#xff0c;点击安装i…

Sun Apr 16 00:00:00 CST 2023格式转换

Date date new Date(); log.info("当前时间为:{}",date); //yyyy-MM-dd HH:mm:ss SimpleDateFormat sdf new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS); String dateTime s…

Android11适配已安装应用列表

Android11适配已安装应用列表 之前做过已安装应用列表的适配&#xff0c;最近国内版SDK升级到33和隐私合规遇到很多问题&#xff0c;于是把已安装应用列表记录一下&#xff1a; 1、在Android11及以上的适配&#xff1a; package com.example.requestinsttallapplistdemoimpo…

电磁兼容EMC理论基础汇总

目录 0. 序言 1. EMC的基础介绍 1.1 EMC电磁兼容的定义 1.2 EMC的重要性 1.3 EMC的三要素 2. 库仑定律 3. 趋肤效应与趋肤深度 4. 电阻抗公式 4.1 电阻 4.2 容抗 4.3 感抗 4.4 电路元件的非理想性 5. 麦克斯韦方程组 5.1 高斯磁定律 5.2 高斯定律 5.3 法拉…

一文讲透Python函数的创建和调用

1.Python提供了函数作为完成某项工作的标准化代码块 Python本质上是一种编程语言&#xff0c;通过编写运行代码的方式实现工作目标。读者可以想象&#xff0c;如果针对机器学习或数据统计分析的每种方法或统计量计算都要用户自行编写代码&#xff0c;那么显然在很多情况下是无…

Rust 语言:认识 Rust

本心、输入输出、结果 文章目录 Rust 语言&#xff1a;认识 Rust前言Rust的特点Rust LOGO Rust 在IT行业的应用前景Rust 是一门系统级编程语言相关链接花有重开日&#xff0c;人无再少年实践是检验真理的唯一标准 Rust 语言&#xff1a;认识 Rust 编辑&#xff1a;简简单单 Onl…

多级缓存自用

1.什么是多级缓存 传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图: 存在下面的问题: •请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈 •Redis缓存失效时,会对数据库产生冲击 多级缓存就是充分利用请求处理的每个环节,添加缓…