从何时你也忌讳空山无人,从何时开始怕遥望|

Drunker•L

园龄:4个月粉丝:0关注:0

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

思路分析:

  1. 问题模型
    • 每一堆香蕉 piles[i],珂珂每小时吃 k 根香蕉。
    • 如果某堆香蕉数目小于 k,珂珂会在一个小时内吃完这一堆。
    • 我们需要找到最小的 k,使得珂珂能够在 h 小时内吃掉所有香蕉。
  2. 计算吃香蕉所需的时间
    • 对于每一堆香蕉 piles[i],珂珂需要的时间是 ceil(piles[i] / k),即香蕉数除以速度 k,向上取整。可以通过 (piles[i] + k - 1) / k 来实现向上取整。
    • 总时间是所有堆所需时间的总和,我们需要确保这个总时间小于等于 h
  3. 二分查找
    • 速度 k 的最小值为 1,最大值为所有香蕉堆中最大的一堆 max(piles)。因为如果 k 超过某堆香蕉的数量,珂珂每小时最多只吃一次。
    • 我们可以对速度 k 进行二分查找,判断在给定的速度下是否可以在 h 小时内吃掉所有香蕉。

算法步骤:

  1. 设置二分查找的范围:最小值为 1,最大值为 max(piles)
  2. 使用 mid 作为当前的速度,计算所有堆香蕉的总吃完时间。
  3. 如果总时间小于等于 h,说明当前速度可能是一个有效的解,尝试减小速度(即 right = mid - 1)。
  4. 如果总时间大于 h,说明当前速度太小,需要增加速度(即 left = mid + 1)。
  5. 最终返回找到的最小速度 k
public class Solution {
    public int minEatingSpeed(int[] piles, int h) {
        int left = 1, right = 0;
        
        // 找到香蕉堆中最大的堆
        for (int pile : piles) {
            right = Math.max(right, pile);
        }

        // 二分查找最小的速度 k
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (canFinish(piles, mid, h)) {
                right = mid - 1;  // 如果能在 h 小时内吃完,则尝试减小速度
            } else {
                left = mid + 1;  // 否则增加速度
            }
        }

        return left;
    }

    // 判断在速度 k 下,是否可以在 h 小时内吃掉所有香蕉
    private boolean canFinish(int[] piles, int k, int h) {
        int hoursNeeded = 0;
        for (int pile : piles) {
            hoursNeeded += (pile + k - 1) / k;  // 计算每堆香蕉需要的时间
        }
        return hoursNeeded <= h;  // 如果总时间不超过 h 小时,则返回 true
    }
}

代码解释:

  1. minEatingSpeed 方法
    • 设置 left 为 1,rightpiles 中最大值(即最大香蕉数)。
    • 通过二分查找找到最小的速度 k,使得在 h 小时内能够吃完所有香蕉。
  2. canFinish 方法
    • 给定速度 k,计算吃掉所有香蕉所需要的时间,并与 h 比较,判断是否能在 h 小时内完成。

[!NOTE]

在 Java 中,可以通过以下两种方式实现向上取整(即对 piles[i] / k 的结果向上取整):

方法 1:使用 Math.ceil 方法

Math.ceil() 函数可以将浮动的结果向上取整为最近的整数。你需要将 piles[i] / k 先转换为浮动值,之后使用 Math.ceil() 方法进行取整。

double result = Math.ceil((double) piles[i] / k);

然而,这会得到一个 double 类型的结果。如果你希望得到一个 int 类型的结果,可以将其转换为 int

int result = (int) Math.ceil((double) piles[i] / k);

方法 2:使用整数运算

如果你只关心整数运算,可以通过简单的数学技巧实现向上取整,而不需要使用浮点数运算。具体来说,(a + b - 1) / b 公式可以用来向上取整 a / b

int result = (piles[i] + k - 1) / k;

这个公式的作用是将被除数 piles[i] 和除数 k 之间的商通过加上 k - 1 来保证向上取整。这是一个非常高效的方式,因为它只依赖于整数运算,不涉及浮点数计算。

本文作者:Drunker•L

本文链接:https://www.cnblogs.com/drunkerl/p/18656174

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Drunker•L  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起