875. 爱吃香蕉的珂珂
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
珂珂喜欢吃香蕉。这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 H 小时后回来。
珂珂可以决定她吃香蕉的速度 K (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 K 根。如果这堆香蕉少于 K 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 H 小时内吃掉所有香蕉的最小速度 K(K 为整数)。
具体题目链接: 题目链接
思路:
题意求的是最小速度k,本质上是在一个范围内求目标值的左边界,也就是从满足的最小值为边界,再往左就不满足了,往右都是满足的。
分析:
珂珂吃香蕉的速度最小为1,最大速度是piles数组中元素的最大值,因为每小时最多吃一堆香蕉,多了的就要加时间,在最小速度和最大速度这个排序区间内求在 H 小时内吃掉所有香蕉的最小速度 K
珂珂吃的速度和时间是此消彼长的关系,吃的速度越快,花的时间越少。吃的速度越慢,花的时间越多。要让珂珂吃得够慢,又能吃完。
那从最慢的k=1开始,让珂珂一小时只吃 1 ,看珂珂能否在 h 小时内吃完。如果吃不完,就按k=2的速度吃,重头吃一遍。一直到找到最小满足的速度 k。
优化:
数据范围:piles.length <= H <= 10^9,k 从 1 开始遍历,效率太低了。k 最小是 1,piles数组中元素的最大值。
也就是,我们要在一个范围里找 k,这个时候,可以想到二分查找:就是用二分查找来搜索目标值的左侧边界,本质上是在一个范围内求目标值的左边界,也就是从满足的最小值为边界,再往左就不满足了,往右都是满足的
当使用「二分查找」算法猜测的速度k恰好使得珂珂在规定的时间内吃完香蕉的时候,还应该去尝试更小的速度是不是还可以保证在规定的时间内吃完香蕉,从而做到边界点最小速度。
这是因为题目问的是「最小速度 」。
细节:
因为珂珂一个小时之内只能选择一堆香蕉吃,因此:每堆香蕉吃完的耗时 = 这堆香蕉的数量 / 珂珂一小时吃香蕉的数量。根据题意,这里的 / 在不能整除的时候,需要 上取整。
代码:
var minEatingSpeed = function(piles, h) {
let left = 1;
let right = Math.max(...piles);
while(left<right) {
//mid的定义是每小时吃的速度
let mid = Math.floor(left + (right-left)/2);
if(check(mid,h,piles)) {
right = mid;
}else {
left = mid+1;
}
}
return left;
};
function check(k, h, piles) {
let speedtime = 0;
for(let i=0;i<piles.length;i++) {
if(piles[i]<k) {
speedtime += 1;
}else {
speedtime += Math.ceil(piles[i]/k);
}
}
if(speedtime>h)return false;
else return true;
}
最后
这是「二分专题」系列文章的第 No.1 篇题解
也是算法系列文章的No.3 篇题解
大佬们多指正。