【滑动窗口】水果成篮

水果成篮

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;
    }
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

红队攻防实战之Access注入

若盛世将倾&#xff0c;深渊在侧&#xff0c;我辈当万死以赴 访问漏洞url: 1.Access联合查询 判断是否有注入 and 11正常&#xff0c;and 12出错 判断字段数 order by 7正常 order by 8出错 爆破出表名并判断回显点为2&#xff0c;5 查看字段内容&#xff0c;将字段名填入回…

37. 解数独

题目描述 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; …

思维模型 反馈效应

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。反馈促进改进。 1 反馈效应的应用 1.1 反馈效应在营销中的应用 1 “可口可乐与百事可乐之战” 在 20 世纪 80 年代&#xff0c;可口可乐公司是全球最大的饮料公司之一&#xff0c;其市场…

常见的线程安全问题及解决

1. 什么是线程安全 线程安全指的是当多个线程同时访问一个共享的资源时&#xff0c;不会出现不确定的结果。这意味着无论并发线程的调度顺序如何&#xff0c;程序都能够按照设计的预期来运行&#xff0c;而不会产生竞态条件&#xff08;race condition&#xff09;或其他并发问…

算法设计与实现--贪心篇

贪心算法 贪心算法是一种在每一步选择中都采取当前状态下最优决策的算法&#xff0c;以期望能够通过一系列局部最优的选择达到全局最优。贪心算法的关键是定义好局部最优的选择&#xff0c;并且不回退&#xff0c;即一旦做出了选择&#xff0c;就不能撤销。 一般来说&#xf…

洛谷 P5711 闰年判断 C++代码

目录 前言 思路点拨 AC代码 结尾 前言 今天我们来做洛谷上的一道题目。 网址&#xff1a;【深基3.例3】闰年判断 - 洛谷 题目&#xff1a; 思路点拨 首先题目让我们输入一个年份&#xff0c;因此我们需要定义一个变量year&#xff0c;来存储输入的年份&#xff1a; in…

Bean的加载控制

Bean的加载控制 文章目录 Bean的加载控制编程式注解式ConditionalOn*** 编程式 public class MyImportSelector implements ImportSelector {Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {try {Class<?> clazz Class.forName("…

Nginx 具体应用

1 Nginx 1.1 介绍 一款轻量级的 Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。它占有的内存少&#xff0c;并发能力强&#xff0c;中国大陆使用 nginx 的网站有&#xff1a;百度、京东、新浪、网易、腾讯、淘宝等。第一个公开版本发布于…

Flyway 数据库版本管理 | 专业解决方案

前言 目前很多公司都是通过人工去维护、同步数据库脚本&#xff0c;但经常会遇到疏忽而遗漏的情况&#xff0c;同时也是非常费力耗时 比如说我们在开发环境对某个表新增了一个字段&#xff0c;而提交测试时却忘了提交该 SQL 脚本&#xff0c;导致出现 bug 而测试中断&#xf…

vs 安装 qt qt扩展 改迅雷下载qt

Qt5.14.2安装教程和VS2019中的qt环境配置-CSDN博客 1 安装qt 社区版 免费 Download Qt OSS: Get Qt Online Installer 2 vs安装 qt vs tools 3 vs添加 qt添加 bin/cmake.exe 路径 3.1 扩展 -> qt versions 3.2 4 新版要源码安装 需要自己安装 安装独立安装的旧版 官网…

go自定义端口监听停用-------解决端口被占用的问题

代码 package mainimport ("fmt""log""net""os/exec""strconv""strings" )func getSelect(beign int, end int) int {var num intfor {_, err : fmt.Scan(&num)if err ! nil {fmt.Println("输入错误&am…

【c】角谷猜想

#include<stdio.h> int coll(int x)//定义函数 {int count0;while(x>1){if(x%20){xx/2;count;}else{x3*x1;count;}}return count; } int main() {int n,num;scanf("%d",&n);int arr[n1];for(int i1;i<n;i)//输入n组数据保存到数组中{scanf("%d&…

Python图表神器:Matplotlib库绘制图表轻松有趣

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Matplotlib是Python中用于绘制图表和数据可视化的重要库。它提供了丰富的功能和灵活性&#xff0c;可用于生成各种类型的图表&#xff0c;从简单的折线图到复杂的三维图表。 1. 基本图表绘制 折线图 Matplotl…

【【Micro Blaze 的 最后补充 与 回顾 】】

Micro Blaze 的 最后补充 与 回顾 Micro Blaze 最小系统 以 MicroBlaze 为核心、LocalMemory&#xff08;片上存储&#xff09;为内存&#xff0c;加上传输信息使用的 UART串口就构成了嵌入式最小系统。当程序比较简单时&#xff0c;Local Memory 可以作为程序的运行空间以及…

如何调用 API | 学习笔记

开发者学堂课程【阿里云 API 网关使用教程:如何调用 API】学习笔记&#xff0c;与课程紧密联系&#xff0c;让用户快速学习知识。 课程地址&#xff1a;阿里云登录 - 欢迎登录阿里云&#xff0c;安全稳定的云计算服务平台 如何调用 API 调用 API 的三要素 要调用 API 需要三…

9-3用结构体定义学生,用函数输出学生成绩

#include<stdio.h>struct student{char name[10];int num;char score[3]; }stu[5]; //结构体输入信息int main(){void print(struct student str[5]);int i,j;for(i0;i<5;i){printf("第%d个学生信息如下&#xff1a;\n",i1);printf("name:");scan…

synchronized的实现原理

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

Redis--14--BigKey 和 热点Key

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 BigKey1.什么是bigkey2.bigkey的危害3.发现bigkeyscan 4.解决bigkey 什么是热点Key&#xff1f;该如何解决1. 产生原因和危害原因危害 2.发现热点key预估发现客户端…

基于深度学习的肺炎CT图像检测诊断系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 深度学习在肺炎CT图像检测诊断方面具有广泛的应用前景。以下是关于肺炎CT图像检测诊断系统的介绍&#xff1a; 任务…