1.题目基本信息
1.1.题目描述
珂珂喜欢吃香蕉。这里有 n 堆香蕉,第 i 堆中有 piles[i] 根香蕉。警卫已经离开了,将在 h 小时后回来。
珂珂可以决定她吃香蕉的速度 k (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 k 根。如果这堆香蕉少于 k 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在 h 小时内吃掉所有香蕉的最小速度 k(k 为整数)。
1.2.题目地址
https://leetcode.cn/problems/koko-eating-bananas/description/
2.解题方法
2.1.解题思路
二分查找
2.2.解题步骤
第一步,判断是否可以用二分查找。因为吃的速度在1到max(piles)之间,且可以判断某个速度下是否能吃完,所以可以使用二分法。
第二步,理解红蓝染色法在该二分过程中的不变特征。红:check不能吃完,蓝:check能吃完;左闭右闭区间:left-1:始终指向红色,right+1始终指向蓝色;最终的left即为最小的能吃完的速度。
第三步,定义check的判断函数,如果速度是speed,那么吃完所有的香蕉需要的总时间即为每堆香蕉数除以速度并上取整的和,如果总时间小于等于h,则可以吃完,反之,吃不完。
第四步,根据check函数和左闭右闭的红蓝染色法二分模板进行编码获得最终的left,最终的left即为题解。
3.解题代码
Python代码
import math
# 二分查找
# 第一步,判断是否可以用二分查找。因为吃的速度在1到max(piles)之间,且可以判断某个速度下是否能吃完,所以可以使用二分法。
# 第二步,理解红蓝染色法在该二分过程中的不变特征。红:check不能吃完,蓝:check能吃完;左闭右闭区间:left-1:始终指向红色,right+1始终指向蓝色;最终的left即为最小的能吃完的速度。
# 第三步,定义check的判断函数,如果速度是speed,那么吃完所有的香蕉需要的总时间即为每堆香蕉数除以速度并上取整的和,如果总时间小于等于h,则可以吃完,反之,吃不完。
# 第四步,根据check函数和左闭右闭的红蓝染色法二分模板进行编码获得最终的left,最终的left即为题解。
class Solution:
def minEatingSpeed(self, piles: List[int], h: int) -> int:
# 红:check不能吃完,蓝:check能吃完;左闭右闭:left-1:始终指向红色,right+1始终指向蓝色;最终的left即为最小的能吃完的速度
def check(speed): # 返回是否能吃完
sumHours=0
for pile in piles:
sumHours+=math.ceil(pile/speed)
return sumHours<=h
left,right=1,max(piles)
while left<=right:
mid=(right-left)//2+left
if not check(mid):
left=mid+1
else:
right=mid-1
return left
C++代码
class Solution {
public:
int minEatingSpeed(vector<int>& piles, int h) {
int left=1;
int right=*max_element(piles.begin(),piles.begin()+piles.size());
while(left<=right){
int mid=(right-left)/2+left;
long long sumHours=0;
for(int pile:piles){
sumHours+=ceil(pile/double(mid));
}
if(sumHours>h){
left=mid+1;
}else{
right=mid-1;
}
}
return left;
}
};