LeetCode热题(JS版) - 875. 爱吃香蕉的珂珂

227 阅读2分钟

题目描述

珂珂喜欢吃香蕉。有N堆香蕉,第i堆中有piles[i]根香蕉。警卫已经离开了这里,珂珂可以在H小时内吃掉所有香蕉,每小时最多吃K根香蕉。 珂珂可以在任意时刻开始吃,不需要从第一堆开始吃,也不需要在最后一堆停止。返回珂珂可以吃掉所有香蕉的最小速度 K(例如:当 H = 4, piles = [3,6,7,11] 时,K = 8.)

示例 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.length <= 10^4 piles.length <= H <= 10^9 1 <= piles[i] <= 10^9

算法

二分查找

实现思路

本题可以使用二分查找算法解决,我们需要在一个区间范围内搜索结果,具体实现如下:

  1. 确定查找的左右边界,左边界为1,右边界为piles数组中最大值;
  2. 计算中间值mid,使用mid来作为K的取值,判断以当前K的取值是否可以在H小时内吃完所有香蕉;
  3. 如果可以吃完,则缩小区间,将右边界更新为mid;否则扩大区间,将左边界更新为mid + 1;
  4. 当左边界等于右边界时,返回最终结果。

代码实现

function canEatAll(piles: number[], H: number, K: number): boolean {
    let hours = 0;
    for (let i = 0; i < piles.length; i++) {
        hours += Math.ceil(piles[i] / K);// 一堆吃完才能下一堆
    }
    return hours <= H;
}

function minEatingSpeed(piles: number[], H: number): number {
    let left = 1;
    let right = Math.max(...piles);

    while (left < right) {
        const mid = Math.floor((left + right) / 2);
        if (canEatAll(piles, H, mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    return left;
}

复杂度分析

  • 时间复杂度:O(NlogM),其中N为piles数组长度,M为piles数组中最大值。我们需要进行一次二分查找,每次判断需要遍历所有香蕉堆,时间复杂度为O(N),因此总时间复杂度为O(NlogM)。
  • 空间复杂度:O(1),我们只使用了常数个变量。