875.爱吃香蕉的珂珂

题目:

珂珂喜欢吃香蕉。这里有 n 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 h 小时后回来。

珂珂可以决定她吃香蕉的速度 k (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 k 根。如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。  

珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。

返回她可以在 h 小时内吃掉所有香蕉的最小速度 kk 为整数)。

示例 1:

输入:piles = [3,6,7,11], h = 8
输出:4

示例 2:

输入:piles = [30,11,23,4,20], h = 5
输出:30

示例 3:

输入:piles = [30,11,23,4,20], h = 6
输出:23

思路:

这个问题是一个典型的二分查找问题,需要找到能够满足条件的最小的速度值。珂珂需要在警卫回来前吃掉所有的香蕉,所以我们需要找到一个速度,使得吃掉所有香蕉的时间不超过给定的h小时。

解决这个问题的步骤如下:

  1. 确定搜索范围:最小的速度是1(每小时至少吃一个香蕉),最大的速度是所有香蕉堆中香蕉数量最多的那一堆(最坏的情况是只有一堆香蕉,且这堆香蕉的数量就是最大速度)。

  2. 二分查找:在确定的搜索范围内,使用二分查找来找到最小的速度。对于每一个中间速度,计算吃掉所有香蕉所需的时间。

  3. 计算时间:对于每个速度,遍历每一堆香蕉,计算吃掉每一堆所需的时间,并将这些时间累加起来。计算每一堆香蕉所需的时间时,如果香蕉堆的数量能够被速度整除,那么所需时间就是香蕉堆数量除以速度;如果不能整除,那么需要向上取整,因为即使最后一分钟没有吃完整个香蕉堆,也会算作一分钟。

  4. 调整搜索范围:如果计算出的总时间小于等于h,说明当前速度可能偏大或者正好是我们要找的速度,因此需要调整搜索范围,缩小到当前速度及其以下的部分;如果计算出的总时间大于h,说明当前速度偏小,需要调整搜索范围到当前速度以上。

  5. 找到最小速度:重复二分查找过程,直到找到最小的速度,使得吃掉所有香蕉的时间不超过h小时。

  6. 返回结果:最后,返回找到的最小速度k

代码: 

C++

class Solution {
public:
    int minEatingSpeed(vector<int>& piles, int h) {

定义了一个名为Solution的类,其中包含一个公共成员函数minEatingSpeed,它接受一个整数向量piles(代表香蕉堆的大小)和一个整数h(代表给定的小时数)。

        int low = 1;
        int high = 0;

初始化二分查找的最低速度low为1(因为至少每分钟吃一个香蕉),最高速度high初始为0,后面会根据香蕉堆的大小更新这个值。

        for (int pile : piles) {
            high = max(high, pile);
        }

遍历所有的香蕉堆,将high更新为当前香蕉堆大小和high中的较大值。这样,high最后会包含最大的香蕉堆大小,即在最坏情况下,最大速度就是最大的香蕉堆大小。

        int k = high;

初始化结果变量khigh,即当前假设的最大速度。

        while (low < high) {

开始一个循环,只要low小于high,就继续二分查找。

            int speed = (high - low) / 2 + low;

计算当前的速度,即lowhigh之间的中间值。

            long time = getTime(piles, speed);

调用getTime函数来计算以当前速度吃完所有香蕉堆需要的时间。

            if (time <= h) {
                k = speed;
                high = speed;
            } else {
                low = speed + 1;

            }

如果计算出的时间小于等于给定的时间h,说明当前速度可能是可行的最小速度。将k更新为当前速度,并将high设置为当前速度,这样在下一次循环中查找的范围就会缩小到当前速度及其以下。如果计算出的时间大于给定的时间h,说明当前速度太小,需要增加速度。因此,将low设置为当前速度加一,这样在下一次循环中查找的范围就会是当前速度以上。

        }
        return k;
   }

循环结束,返回最终计算出的最小速度k。

long getTime(const vector<int>& piles, int speed) {
        long time = 0;
        for (int pile : piles) {
            int curTime = (pile + speed - 1) / speed;
            time += curTime;
        }
        return time;
    }
};

定义了一个名为getTime的辅助函数,它接受一个整数向量piles和一个整数speed,返回以当前速度吃完所有香蕉堆需要的时间。遍历每一堆香蕉,计算吃完每一堆需要的时间,并累加到总时间time中。这里(pile + speed - 1) / speed确保了即使最后一分钟没有吃完整个香蕉堆,也会算作一分钟。函数结束,返回计算出的总时间。

Python:

import math

class Solution:
    def minEatingSpeed(self, piles: List[int], h: int) -> int:
        low, high = 1, max(piles)
        while low < high:
            mid = (low + high) // 2
            if self.canFinish(piles, mid, h):
                high = mid
            else:
                low = mid + 1
        return low

    def canFinish(self, piles: List[int], speed: int, h: int) -> bool:
        time = 0
        for pile in piles:
            time += math.ceil(pile / speed)
        return time <= h

对代码的详细解释:

导入math模块,以便使用math.ceil函数进行向上取整。定义一个名为Solution的类,用于包含解决问题的方法。定义一个名为minEatingSpeed的方法,它接受一个整数列表piles(代表香蕉堆的大小)和一个整数h(代表给定的小时数),并返回一个整数(最小速度)。初始化二分查找的最低速度low为1,最高速度high为香蕉堆中的最大值,这是可能的最大速度。开始一个循环,只要low小于high,就继续二分查找。计算中间速度mid,这是当前搜索范围的中间值。调用canFinish方法来检查以中间速度mid是否能在h小时内吃完所有的香蕉堆。如果可以吃完,说明当前速度可能偏大或者正好是我们要找的速度,因此将high设置为mid,缩小搜索范围到中间速度及其以下。如果无法吃完,说明当前速度偏小,需要增加速度,因此将low设置为mid + 1,缩小搜索范围到中间速度以上。循环结束后,返回low,这是珂珂可以在h小时内吃掉所有香蕉的最小速度。定义一个名为canFinish的辅助方法,它接受一个整数列表piles,一个整数speed和一个整数h,返回一个布尔值,表示以当前速度是否能在h小时内吃完所有的香蕉堆。初始化总时间time为0。遍历每一堆香蕉,计算吃完每一堆需要的时间,并累加到总时间time中。使用math.ceil确保即使最后一分钟没有吃完整个香蕉堆,也会算作一分钟。返回一个布尔值,表示总时间是否小于等于给定的时间h

这是我对这一题的一些看法, 如果大家觉得我的想法还不错的话,留下一个小小的赞波!!!

  • 44
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值