题目描述
珂珂喜欢吃香蕉。这里有n堆香蕉,第i堆中有piles[i]根香蕉。警卫已经离开了,将在h小时后回来。
珂珂可以决定她吃香蕉的速度k(单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉k根。如果这堆香蕉少于k根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。
珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。
返回她可以在h小时内吃掉所有香蕉的最小速度k(k为整数)。
示例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 <= 104piles.length <= h <= 1091 <= piles[i] <= 109
题解
力扣原题链接
思路:二分
从题目来看,这道题肯定有解,所以不需要考虑
h <= 香蕉堆数的情况接下来考虑H = 香蕉堆数量时, 结果肯定为max(香蕉堆香蕉的数量). 因为每个小时要处理一个香蕉堆,要保证能在一个小时内吃完一堆香蕉
最后考虑H > 香蕉堆数量时,怎么确定k的值。采用二分进行确定,left = 1, right = max(所有香蕉堆香蕉数量),每次枚举mid = (right + left) / 2是否可以在指定时间内把所有香蕉堆上香蕉吃完。
- 不能吃完,更新left = mid + 1
- 能吃完,更新right = mid
二分退出条件为left == right
最终的left的值就是结果。
额外注意:所有香蕉堆中香蕉数量 可能超过int范围,需要使用long范围。
c++
class Solution { public: // 计算所需时间是否小于h bool check(vector<int>& piles, long k, int h) { int needHour = 0; int n = piles.size(); for (int i = 0; i < n; i++) { // 向上取整 needHour += ( piles[i] + k - 1) / k; } return needHour <= h; } int minEatingSpeed(vector<int>& piles, int h) { long left = 1, right = 0; int n = piles.size(); for (int i = 0; i < n; i++) { right += piles[i]; } // 二分 while (left < right) { long mid = (left + right) >> 1; if (check(piles, mid, h)) { right = mid; } else { left = mid + 1; } } return left; } };JAVA
class Solution { // 计算在速度 k 下吃完是否不超过 h 小时 private boolean check(int[] piles, long k, int h) { long needHour = 0; for (int pile : piles) { // 向上取整 needHour += (pile + k - 1) / k; } return needHour <= h; } public int minEatingSpeed(int[] piles, int h) { long left = 1, right = 0; for (int pile : piles) { right += pile; } // 二分查找最小可行速度 while (left < right) { long mid = (left + right) >> 1; if (check(piles, mid, h)) { right = mid; } else { left = mid + 1; } } return (int) left; } }Python
classSolution:# 计算在速度 k 下吃完是否不超过 h 小时defcheck(self,piles,k,h):needHour=0forpileinpiles:# 向上取整needHour+=(pile+k-1)//kreturnneedHour<=hdefminEatingSpeed(self,piles,h):left,right=1,sum(piles)# 二分查找whileleft<right:mid=(left+right)//2ifself.check(piles,mid,h):right=midelse:left=mid+1returnleftJavaScript
/** * @param {number[]} piles * @param {number} h * @return {number} */varminEatingSpeed=function(piles,h){// 计算在速度 k 下吃完是否不超过 h 小时functioncheck(k){letneedHour=0;for(letpileofpiles){// 向上取整needHour+=Math.floor((pile+k-1)/k);}returnneedHour<=h;}letleft=1;letright=piles.reduce((a,b)=>a+b,0);// 二分查找while(left<right){letmid=Math.floor((left+right)/2);if(check(mid)){right=mid;}else{left=mid+1;}}returnleft;};Go
funcminEatingSpeed(piles[]int,hint)int{// 检查在速度 k 下是否可以在 h 小时内吃完check:=func(kint)bool{needHour:=0for_,pile:=rangepiles{// 向上取整:(pile + k - 1) / kneedHour+=(pile+k-1)/k}returnneedHour<=h}left,right:=1,0for_,pile:=rangepiles{right+=pile}// 二分查找最小可行速度forleft<right{mid:=(left+right)>>1ifcheck(mid){right=mid}else{left=mid+1}}returnleft}