一、Problem
Koko loves to eat bananas. There are N piles of bananas, the i-th pile has piles[i] bananas. The guards have gone and will come back in H hours.
Koko can decide her bananas-per-hour eating speed of K. Each hour, she chooses some pile of bananas, and eats K bananas from that pile. If the pile has less than K bananas, she eats all of them instead, and won’t eat any more bananas during this hour.
Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back.
Return the minimum integer K such that she can eat all the bananas within H hours.
Input: piles = [3,6,7,11], H = 8
Output: 4
二、Solution
方法一:二分
目标是求吃完所有香蕉的最小速度,而数值大的速度 s 能在 H 小时内吃完,那么 > s 的速度也一定能,所以只需要缩小查找速度的边界即可。
class Solution {
int H, ps[];
boolean ck(int s) {
int h = 0;
for (int p : ps) {
h += p / s;
if (p % s != 0) h++;
if (h > H)
return false;
}
return true;
}
public int minEatingSpeed(int[] piles, int H) {
int l = 1, r = 0;
this.H = H; this.ps = piles;
for (int p : ps) if (p > r) {
r = p;
}
while (l < r) {
int s = l + r >>> 1;
if (ck(s)) r = s;
else l = s+ 1;
}
return r;
}
}
向上取整的写法还有比较高效的写法:
h += (p+s-1) / s
证明: 等于 向上取整的结果正确性
- 如果 ,有 ,
- 如果 ,又有 ,
class Solution {
int H, ps[];
boolean ck(int s) {
int h = 0;
for (int p : ps) {
h += (p+s-1)/s;
if (h > H)
return false;
}
return true;
}
public int minEatingSpeed(int[] piles, int H) {
int l = 1, r = 0;
this.H = H; this.ps = piles;
for (int p : ps) if (p > r)
r = p;
while (l < r) {
int mid = l + r >>> 1;
if (ck(mid)) r = mid;
else l = mid + 1;
}
return r;
}
}
复杂度分析
- 时间复杂度:,
- 空间复杂度:,