Koko Eating Bananas
Koko has n piles of bananas, where piles[i] is the number in pile i, and h hours before the guards return. She picks one integer speed k, in bananas per hour. Each hour she eats k bananas from a single pile; if that pile has fewer than k left, she finishes it and waits out the rest of the hour without moving to another pile. Return the smallest k that lets her finish every pile within h hours. h is at least the number of piles, so an answer always exists.
Examples
piles = [3,6,7,11], h = 8 returns 4
At speed 4 the piles take 1 + 2 + 2 + 3 = 8 hours, which fits. At speed 3 they take 1 + 2 + 3 + 4 = 10 hours, which is too many.
piles = [30,11,23,4,20], h = 5 returns 30
With 5 piles and only 5 hours, every pile must be finished in a single hour, so k must be at least the largest pile, 30.
piles = [30,11,23,4,20], h = 6 returns 23
At speed 23 the piles take 2 + 1 + 1 + 1 + 1 = 6 hours. At speed 22 both the 30 and the 23 pile need 2 hours, for 7 in total.
Constraints
- 1 <= piles.length <= 10^4
- piles.length <= h <= 10^9
- 1 <= piles[i] <= 10^9
Hints
The eating speed itself is bounded and monotonic, slower speeds risk running out of time and faster always work. What can you search?
Binary search on the answer (the eating speed).
Search in [1, max(piles)]. For a candidate k, hours needed = sum(ceil(p / k)). If hours <= h, the speed works, try slower (hi = mid); otherwise try faster (lo = mid + 1). Return lo.
Drill This: Your Approach First
Approach
Hours needed only go down as the speed goes up, so search the speed range 1 to max(piles) for the first speed that fits. For a candidate mid, the hours are the sum of ceil(p / mid) over all piles, computed as (p + mid - 1) / mid in integer math. If that is at most h, mid works and something slower might too, so set hi = mid; otherwise set lo = mid + 1. O(n log m) time, where m = max(piles), and O(1) space.
Time
O(n log m)
Space
O(1)
Pitfall
Solutions
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int lo = 1, hi = 0;
for (int p : piles) hi = Math.max(hi, p);
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
long hours = 0;
for (int p : piles) hours += (p + mid - 1) / mid;
if (hours <= h) hi = mid;
else lo = mid + 1;
}
return lo;
}
}class Solution:
def minEatingSpeed(self, piles, h: int) -> int:
lo, hi = 1, max(piles)
while lo < hi:
mid = (lo + hi) // 2
hours = sum((p + mid - 1) // mid for p in piles)
if hours <= h:
hi = mid
else:
lo = mid + 1
return lo