题目描述
珂珂喜欢吃香蕉。有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,右边界为piles数组中最大值;
- 计算中间值mid,使用mid来作为K的取值,判断以当前K的取值是否可以在H小时内吃完所有香蕉;
- 如果可以吃完,则缩小区间,将右边界更新为mid;否则扩大区间,将左边界更新为mid + 1;
- 当左边界等于右边界时,返回最终结果。
代码实现
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),我们只使用了常数个变量。