24/12/24 力扣每日一题 # 题目解析:1705. 吃苹果的最大数目 全网最详细解释

news2024/12/26 21:36:25

题目解析:1705. 吃苹果的最大数目

问题描述

你有一棵特殊的苹果树,连续 n 天,每天树上可能会长出若干个苹果。对于第 i 天:

  • apples[i] 表示当天长出的苹果数量。
  • 这些苹果将在 days[i] 天后腐烂,也就是说,这些苹果在第 i + days[i] 天时就无法食用了。

你计划每天最多吃一个苹果,以保证营养均衡。需要注意的是,即使在 n 天之后,你仍然可以继续吃苹果,直到所有苹果都腐烂。

目标: 返回你最多可以吃掉的苹果数量。

示例解析

示例 1

输入:apples = [1,2,3,5,2], days = [3,2,1,4,2]
输出:7

解释:

  • 第1天,树上有1个苹果,3天后腐烂(第4天)。
  • 第2天,树上有2个苹果,2天后腐烂(第4天)。
  • 第3天,树上有3个苹果,1天后腐烂(第4天)。
  • 第4天,树上有5个苹果,4天后腐烂(第8天)。
  • 第5天,树上有2个苹果,2天后腐烂(第7天)。

你可以按照如下方式吃苹果:

  1. 第1天,吃第1天长出的1个苹果。
  2. 第2天,吃第2天长出的2个苹果中的一个。
  3. 第3天,吃第2天长出的另一个苹果(第3天苹果会腐烂)。
  4. 第4天到第7天,你吃的都是第4天长出的苹果。

总共吃掉7个苹果。

示例 2

输入:apples = [3,0,0,0,0,2], days = [3,0,0,0,0,2]
输出:5

解释:

  • 第1天第3天,吃的都是第1天长出的苹果。
  • 第4天第5天不吃苹果。
  • 第6天第7天,吃的都是第6天长出的苹果。

总共吃掉5个苹果。

解题思路

为了最大化吃掉的苹果数量,我们需要合理安排每天吃哪个苹果,以避免苹果腐烂。由于苹果有保质期(即腐烂时间),需要优先吃那些即将腐烂的苹果。

步骤详解

  1. 数据结构选择:

    • 使用**最小堆(Min Heap)**来管理苹果,堆中存储的是每批苹果的过期时间和数量。这样,堆顶元素始终是最早过期的一批苹果,便于优先处理。
  2. 处理流程:

    • 遍历每一天,处理当天生成的苹果。
    • 移除堆中已经腐烂的苹果。
    • 添加当天新生成的苹果到堆中。
    • 吃掉堆顶的苹果(即最早腐烂的苹果)。
    • 统计总共吃掉的苹果数量。
    • 继续循环,直到所有生成的苹果都被处理完毕,即使超过n天。
  3. 循环条件:

    • 循环继续的条件是当前天数 i 还在生成苹果的范围内,或者堆中还有未腐烂的苹果。即使用 while i < len(apples) or heap:

关键点

  • 优先吃即将腐烂的苹果,避免浪费。
  • 堆的使用确保每次取出的都是最早过期的苹果。
  • 继续循环直到所有苹果都被处理完毕,包括n天之后的苹果。

代码实现

以下是完整的 Python 代码,并附带详细解释:

import heapq
from typing import List

class Solution:
    def eatenApples(self, apples: List[int], days: List[int]) -> int:
        ans = i = 0
        h = []
        while i < len(apples) or h:
            # 移除已经腐烂的苹果
            while h and h[0][0] <= i:
                heapq.heappop(h)
            # 如果当天有新苹果生成,加入堆中
            if i < len(apples) and apples[i] > 0:
                heapq.heappush(h, [i + days[i], apples[i]])
            # 吃掉最早腐烂的苹果
            if h:
                ans += 1
                h[0][1] -= 1  # 吃掉一个苹果
                if h[0][1] == 0:
                    heapq.heappop(h)
            i += 1  # 进入下一天
        return ans

代码详解

  1. 导入必要的模块:

    import heapq
    from typing import List
    
    • heapq 用于实现最小堆。
    • List 是类型提示的一部分,帮助代码更易读。
  2. 初始化变量:

    ans = i = 0
    h = []
    
    • ans 用于统计总共吃掉的苹果数量。
    • i 表示当前天数,从0开始。
    • h 是一个空的最小堆,用于存储苹果的过期时间和数量。
  3. 主循环:

    while i < len(apples) or h:
    
    • 条件解释:
      • i < len(apples):确保在所有生成苹果的天数内,处理每天生成的苹果。
      • or h:确保即使在所有天数之后,仍然有未腐烂的苹果时,继续处理堆中的苹果。
  4. 移除已腐烂的苹果:

    while h and h[0][0] <= i:
        heapq.heappop(h)
    
    • 检查堆顶的苹果是否已经腐烂(即过期时间 <= 当前天数)。
    • 如果是,移出堆顶元素,直到堆顶的苹果都是未腐烂的。
  5. 添加当天新生成的苹果:

    if i < len(apples) and apples[i] > 0:
        heapq.heappush(h, [i + days[i], apples[i]])
    
    • 如果当前天数 i 在苹果生成的天数范围内,并且当天有苹果生成 (apples[i] > 0),则计算这些苹果的过期时间 i + days[i]
    • [i + days[i], apples[i]] 作为一个列表加入堆中。
  6. 吃掉苹果:

    if h:
        ans += 1
        h[0][1] -= 1  # 吃掉一个苹果
        if h[0][1] == 0:
            heapq.heappop(h)
    
    • 如果堆中还有未腐烂的苹果,取出堆顶元素 [过期时间, 剩余数量]
    • 吃掉一个苹果,ans 增加1,剩余数量 减少1。
    • 如果这一批苹果已经被全部吃完(剩余数量 == 0),将其移出堆中。
  7. 进入下一天:

    i += 1
    
    • 增加 i,进入下一天的循环。
  8. 返回结果:

    return ans
    
    • 循环结束后,返回总共吃掉的苹果数量。

堆的自动排序机制

  • 最小堆性质:

    • 使用 heapq 实现的最小堆保证堆顶元素始终是最小的。
    • 堆中存储的是 [过期时间, 苹果数量],所以堆顶元素是过期时间最早的一批苹果。
  • 自动排序:

    • 每次将新苹果 [i + days[i], apples[i]] 推入堆中后,heapq 会自动维护堆的排序。
    • 这样,堆顶始终是过期时间最早的苹果,确保优先吃掉即将腐烂的苹果。

为什么需要 or h

  • 处理生成后仍可食用的苹果:

    • 在前 n 天内,苹果会不断生成并加入堆中,每批苹果有其各自的保质期。
    • 一些苹果的保质期可能会超过 n 天。如果不使用 or h,一旦 i 达到 n,循环就会停止,即使堆中还有未腐烂的苹果,无法被吃掉,导致浪费。
  • 最大化吃掉的苹果数量:

    • 通过继续循环,只要堆中还有未腐烂的苹果,就可以继续吃苹果。这确保了你在前 n 天之外,仍然可以吃到那些在 n 天后仍未腐烂的苹果。

具体示例说明

考虑以下示例:

apples = [2, 1, 1, 0, 0, 0]
days = [5, 3, 2, 0, 0, 0]

天数和堆的变化:

  • 第0天(i=0):

    • 生成2个苹果,过期时间为 0 + 5 = 5
    • 堆中有 [[5, 2]]
    • 吃掉一个苹果,堆中剩余 [[5, 1]]
  • 第1天(i=1):

    • 生成1个苹果,过期时间为 1 + 3 = 4
    • 堆中有 [[4, 1], [5, 1]]
    • 吃掉过期时间最早的苹果(过期时间4),堆中剩余 [[5, 1]]
  • 第2天(i=2):

    • 生成1个苹果,过期时间为 2 + 2 = 4
    • 堆中有 [[4, 1], [5, 1]]
    • 吃掉过期时间4的苹果,堆中剩余 [[5, 1]]
  • 第3天(i=3):

    • 没有新苹果生成。
    • 检查堆中苹果是否过期:
      • 4 <= 3 不成立,堆中仍有 [[5, 1]]
    • 吃掉堆顶的苹果,堆中剩余 [[5, 0]],移出堆中。
  • 第4天(i=4)和第5天(i=5):

    • 没有新苹果生成。
    • 堆中没有未腐烂的苹果,循环结束。

如果不使用 or h

  • i 达到 6 时,循环会停止,无法继续处理堆中的苹果,导致部分苹果未被吃掉。

时间与空间复杂度分析

  • 时间复杂度: O(n log n)

    • 每天可能需要进行一次 heappushheappop 操作,堆的操作时间复杂度为 O(log n)。
    • 因此,总体时间复杂度为 O(n log n)。
  • 空间复杂度: O(n)

    • 堆中可能会存储所有未腐烂的苹果,最坏情况下需要 O(n) 的空间。

总结

通过使用最小堆,我们能够高效地管理苹果的过期时间,确保每次都优先吃掉即将腐烂的苹果,从而最大化吃掉的苹果数量。关键在于合理使用堆的性质,确保在所有天数内及之后都能处理好所有苹果,避免浪费。

希望通过以上详细的解析,你能够更好地理解这道题目以及对应的解题代码。如果还有疑问,欢迎继续讨论!

参考代码

以下是完整的 Python 代码实现:

import heapq
from typing import List

class Solution:
    def eatenApples(self, apples: List[int], days: List[int]) -> int:
        ans = i = 0
        h = []
        while i < len(apples) or h:
            # 移除已经腐烂的苹果
            while h and h[0][0] <= i:
                heapq.heappop(h)
            # 如果当天有新苹果生成,加入堆中
            if i < len(apples) and apples[i] > 0:
                heapq.heappush(h, [i + days[i], apples[i]])
            # 吃掉最早腐烂的苹果
            if h:
                ans += 1
                h[0][1] -= 1  # 吃掉一个苹果
                if h[0][1] == 0:
                    heapq.heappop(h)
            i += 1  # 进入下一天
        return ans

常见问题解答

1. 为什么使用最小堆来管理苹果?

使用最小堆的主要原因是我们需要优先处理即将腐烂的苹果。最小堆保证堆顶元素是最早过期的一批苹果,这样每次吃苹果时都能优先选择即将腐烂的苹果,最大限度地避免浪费。

2. 为什么循环条件中需要 or h

or h 确保即使在所有生成苹果的天数结束后,仍然能够继续处理堆中的剩余苹果。这样可以确保在 n 天之后仍然可以吃掉那些在 n 天后仍未腐烂的苹果,从而最大化吃掉的苹果数量。

3. 堆中存储的 [i + days[i], apples[i]] 的含义是什么?

  • i + days[i] 表示这些苹果的过期时间,即第 i + days[i] 天时,这些苹果将会腐烂。
  • apples[i] 表示当天生成的苹果数量。

这样,堆中存储的每个元素都是一批苹果的过期时间和数量,便于管理和优先处理。

4. 如何确保堆中的苹果都是未腐烂的?

在每一天开始时,通过以下代码段移除已经腐烂的苹果:

while h and h[0][0] <= i:
    heapq.heappop(h)

这段代码检查堆顶的苹果是否已经腐烂(即过期时间 <= 当前天数),如果是,则将其移出堆中。这样,堆中始终只保留未腐烂的苹果。

5. 如何处理当天没有新苹果生成的情况?

如果当天没有新苹果生成,apples[i] 为0,条件 if i < len(apples) and apples[i] > 0: 不满足,因此不会将新苹果加入堆中。但如果堆中还有未腐烂的苹果,仍然会继续吃苹果,直到所有苹果都被吃掉或腐烂。

总结

通过合理利用最小堆的特性,我们能够高效地管理苹果的过期时间,确保每次都优先吃掉即将腐烂的苹果,从而最大化吃掉的苹果数量。这道题考察了对优先队列(堆)的应用,以及如何在有限条件下优化资源的使用。掌握了这种思路和技巧,不仅能解决类似的问题,还能提升对数据结构的理解和应用能力。

进一步阅读

  • Python heapq 模块官方文档
  • 优先队列的实现与应用

代码运行示例

以下是一个完整的代码运行示例,帮助你更好地理解代码的执行过程:

import heapq
from typing import List

class Solution:
    def eatenApples(self, apples: List[int], days: List[int]) -> int:
        ans = i = 0
        h = []
        while i < len(apples) or h:
            # 移除已经腐烂的苹果
            while h and h[0][0] <= i:
                heapq.heappop(h)
            # 如果当天有新苹果生成,加入堆中
            if i < len(apples) and apples[i] > 0:
                heapq.heappush(h, [i + days[i], apples[i]])
            # 吃掉最早腐烂的苹果
            if h:
                ans += 1
                h[0][1] -= 1  # 吃掉一个苹果
                if h[0][1] == 0:
                    heapq.heappop(h)
            i += 1  # 进入下一天
        return ans

# 示例测试
if __name__ == "__main__":
    solution = Solution()
    # 示例 1
    apples = [1,2,3,5,2]
    days = [3,2,1,4,2]
    print(solution.eatenApples(apples, days))  # 输出: 7

    # 示例 2
    apples = [3,0,0,0,0,2]
    days = [3,0,0,0,0,2]
    print(solution.eatenApples(apples, days))  # 输出: 5

    # 自定义示例
    apples = [2,1,1,0,0,0]
    days = [5,3,2,0,0,0]
    print(solution.eatenApples(apples, days))  # 输出: 5

输出:

7
5
5

通过这些示例,你可以观察到代码在不同输入下的表现,进一步理解代码的工作原理。

结束语

希望这篇博客能够帮助你深入理解 1705. 吃苹果的最大数目 这道题的解题思路和实现方法。通过合理利用数据结构(最小堆)和优化循环条件,我们能够高效地解决这个问题,最大化吃掉的苹果数量。如果你在学习过程中有任何疑问或建议,欢迎在评论区交流讨论!

版权声明

本文为个人学习笔记,转载请注明出处。

标签

  • 算法
  • 优先队列
  • 贪心算法
  • Python
  • 数据结构

相关企业

  • LeetCode
  • Google
  • Microsoft
  • Facebook

提示

在解题过程中,合理选择和使用数据结构(如最小堆)是关键。此外,理解题目要求和示例有助于明确解题思路。

相关链接

  • LeetCode 1705. 吃苹果的最大数目
  • Python heapq 使用指南
  • 优先队列详解

交流与反馈

如果你对这篇博客有任何建议或疑问,欢迎在下方留言交流。你的反馈是我不断改进的动力!


感谢阅读!祝你学习愉快,算法之路越走越宽!

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

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

相关文章

知识梳理笔记--Kerberos 协议

Kerberos 协议概述 Kerberos 是一种计算机网络认证协议&#xff0c;旨在为不安全的网络提供强认证服务。它通过中心化的身份验证系统&#xff08;即 Key Distribution Center&#xff0c;KDC&#xff09;来确保通信双方的身份验证和数据加密。Kerberos 协议主要用于确保计算机系…

9个用于测试自动化的最佳AI测试工具(2024)

选择一款优质的基于生成式AI人工智能的测试工具能够确保测试过程的准确性和效率&#xff0c;从而加速整个软件测试周期。相反&#xff0c;设计不佳的测试工具可能无法发现错误&#xff0c;并可能存在安全问题。它们可能产生误报或漏报&#xff0c;误导开发与测试团队&#xff0…

uni-app 跨端开发精美开源UI框架推荐

&#x1f380;&#x1f380;&#x1f380;uni-app 跨端开发系列 &#x1f380;&#x1f380;&#x1f380; 一、uni-app 组成和跨端原理 二、uni-app 各端差异注意事项 三、uni-app 离线本地存储方案 四、uni-app UI库、框架、组件选型指南 五、uni-app 蓝牙开发 六、uni-app …

【1224】数据结构(sizeof/数组的长度定义/读取字符串函数/线性表长度/左值右值/静态变量/指针与引用)

1.对一维整型数组a的正确说明是 #define SIZE 10 (换行) int a[SIZE];说法是否正确&#xff1f; 正确 数组的SIZE可以用宏定义&#xff0c;但不能用变量 2.如有定义&#xff1a;char str[20];&#xff0c;能将从键盘输入的字符串“How are you”保存到 str 数组的语句是&#x…

强化特种作业管理,筑牢安全生产防线

在各类生产经营活动中&#xff0c;特种作业由于其操作的特殊性和高风险性&#xff0c;一直是安全生产管理的重点领域。有效的特种作业管理体系涵盖多个关键方面&#xff0c;从作业人员的资质把控到安全设施的配备维护&#xff0c;再到特种设备的精细管理以及作业流程的严格规范…

(六)循环神经网络_基本的RNN

一、提出背景 前馈神经网络不考虑数据之间的关联性&#xff0c;网络的输出只和当前时刻网络的输入相关。然而&#xff0c;现实问题中存在着很多序列型的数据&#xff08;文本、语音以及视频等&#xff09;。 例如&#xff1a;室外的温度是随着气候的变化而周期性的变化的&…

Dockerfile的用法

Dockerfile的用法 示例 `Dockerfile`使用 `Dockerfile` 创建 Docker 镜像`Dockerfile` 指令详解其他常用指令总结Dockerfile 是一个文本文件,包含了用于创建 Docker 镜像的一系列指令。这些指令描述了镜像的基础、所安装的软件、文件的复制、环境变量的设置以及其他配置。下面…

60.基于SSM的个人网站的设计与实现(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;个人网站是在MySQL中建立数据表保存信息&#xff0c;运用SSMVue框架和Java语言编写。并按照软件设计开发流程进行设计实现充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SSM的网…

B端UI设计规范是什么?

一、B端UI设计规范是什么&#xff1f; B端UI设计规范是一套针对企业级应用界面设计的全面规则和标准&#xff0c;旨在确保产品界面的一致性、可用性和用户体验。 二、B端UI设计规范要素说明 B端UI设计的基本要素包括设计原则、主题、布局、颜色、字体、图标、按钮和控件、交互…

GPT人工智能在医疗文档中的应用

应用场景 用于文档的整理。主要是针对医疗方面的文档整理。病人在打官司或者办理其他业务时&#xff0c;需要把很多文档整理成册并添加目录、编写概要&#xff08;Summary&#xff09;。这些文档有电子版本的&#xff0c;有纸质的扫描件&#xff0c;还有拍照&#xff08;一般是…

unity 打包出来的所有执行文件内容打包成一个exe程序

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、使用Enigma Virtual Box1.下载安装包&#xff08;根据需要32位还是64位。一般是64位&#xff09;2.改个语言&#xff0c;方便使用&#xff08;改了后重启才…

vtie项目中使用到了TailwindCSS,如何打包成一个单独的CSS文件(优化、压缩)

在不依赖 Vite 或其他构建工具的情况下&#xff0c;使用 TailwindCSS CLI 快速生成独立的 CSS 文件是一种简单高效的方法&#xff0c;适合需要纯样式文件的场景。 这个项目中&#xff0c;使用到了tailwindCss, 需要把里面的样式打包出来&#xff0c;给其他项目用。 使用命令生…

物联网网络中的设备认证方法

论文标题&#xff1a;DEVICE AUTHENTICATION METHOD IN INTERNET OF THINGS NETWORKS&#xff08;物联网网络中的设备认证方法&#xff09; 作者信息&#xff1a; A.Ya. Davletova&#xff0c;West Ukrainian National University, 11, Lvivska Str. Ternopil, 46009, Ukraine…

重温设计模式--迭代器模式

文章目录 迭代器模式&#xff08;Iterator Pattern&#xff09;概述迭代器模式的结构迭代器模式UML图C 代码示例应用场景 迭代器模式&#xff08;Iterator Pattern&#xff09;概述 定义&#xff1a; 迭代器模式是一种行为型设计模式&#xff0c;它提供了一种方法来顺序访问一个…

大数据机器学习算法和计算机视觉应用07:机器学习

Machine Learning Goal of Machine LearningLinear ClassificationSolutionNumerical output example: linear regressionStochastic Gradient DescentMatrix Acceleration Goal of Machine Learning 机器学习的目标 假设现在有一组数据 x i , y i {x_i,y_i} xi​,yi​&…

华院计算参与项目再次被《新闻联播》报道

12月17日&#xff0c;央视《新闻联播》播出我国推进乡村振兴取得积极进展。其中&#xff0c;华院计算参与的江西省防止返贫监测帮扶大数据系统被报道&#xff0c;该系统实现了由原来的“人找人”向“数据找人”的转变&#xff0c;有效提升监测帮扶及时性和有效性&#xff0c;守…

【视觉惯性SLAM:相机成像模型】

相机成像模型介绍 相机成像模型是计算机视觉和图像处理中的核心内容&#xff0c;它描述了真实三维世界如何通过相机映射到二维图像平面。相机成像模型通常包括针孔相机的基本成像原理、数学模型&#xff0c;以及在实际应用中如何处理相机的各种畸变现象。 一、针孔相机成像原…

使用RTP 协议 对 H264 封包和解包,h264的avpacket和NAL的关系

学习内容&#xff1a; 本章探讨如何将h264的 avpacket的视频 数据&#xff0c;通过RTP协议发送到 流媒体 服务器 或者 对端接受者。 前提 我们在将 YUV数据变成avframe后&#xff0c;通过h264 编码变成AVPacket&#xff0c;例如&#xff0c;在安防项目中&#xff0c;或者直播…

python 随笔80%核心笔记(一)

目录 一、海龟 二、pygame 三、函数 四、类与对象 五、列表与元组 六、其他 1、格式化输出 2、最大公约数、最小公倍数 3、print、多变量一起定义赋值、end以及列表的方法 4、序列重复、字符串方法、其他列表方法、input 5、字典的方法、ASCII码转换、返回值、修改私人…

MySQL数据库函数——字符函数

目录 引言 常用字符函数表 举例 例子一——工号前加0凑够5位 引言 字符函数&#xff0c;顾名思义就是运用在字符串的函数&#xff0c;下列是一些较为常用的字符函数。 常用字符函数表 函数功能concat&#xff08;S1,S2,.....Sn&#xff09;字符串拼接&#xff0c;将S1&…