Koko Eating Bananas
Problem Description
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 will not eat any more bananas during this hour.
Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.
Return the minimum integer k such that she can eat all the bananas within h hours.
Examples
Example 1:Input: piles = [3,6,7,11], h = 8 Output: 4
Input: piles = [30,11,23,4,20], h = 5 Output: 30
Input: piles = [30,11,23,4,20], h = 6 Output: 23
Constraints
1 <= piles.length <= 10⁴piles.length <= h <= 10⁹1 <= piles[i] <= 10⁹
Binary Search on Answer Space
The eating speed k must reside in the range [1, max(piles)].
Instead of scanning every possible speed, we can use binary search on this answer range.
We set left = 1 and right = max(piles).
At each step, calculate the midpoint speed mid.
Compute the total hours needed to finish all piles at speed mid using:
hours_needed = sum(ceil(pile / mid)).
- If
hours_needed <= h,midis a valid speed. We record it as a candidate and attempt to find a slower speed by searching the left half:right = mid - 1. - If
hours_needed > h,midis too slow, so we must search the right half:left = mid + 1.
Solution 1: Binary Search on Speed Range
Perform binary search over the possible eating speeds, validating hour totals.
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int left = 1;
int right = 0;
for (int pile : piles) {
right = Math.max(right, pile); // speed upper bound
}
int result = right;
while (left <= right) {
int mid = left + (right - left) / 2;
if (canEatAll(piles, mid, h)) {
result = mid; // record candidate
right = mid - 1; // try slower speeds
} else {
left = mid + 1; // try faster speeds
}
}
return result;
}
private boolean canEatAll(int[] piles, int speed, int h) {
long totalHours = 0;
for (int pile : piles) {
// Equivalent to ceil(pile / speed) without floating-point math
totalHours += (pile + speed - 1) / speed;
}
return totalHours <= h;
}
}class Solution:
def minEatingSpeed(self, piles: list[int], h: int) -> int:
left = 1
right = max(piles)
result = right
def can_eat_all(speed: int) -> bool:
total_hours = 0
for pile in piles:
# Equivalent to ceil(pile / speed)
total_hours += (pile + speed - 1) // speed
return total_hours <= h
while left <= right:
mid = left + (right - left) // 2
if can_eat_all(mid):
result = mid # record candidate
right = mid - 1 # try slower
else:
left = mid + 1 # try faster
return result#include <vector>
#include <algorithm>
class Solution {
private:
bool canEatAll(const std::vector<int>& piles, int speed, int h) {
long long totalHours = 0;
for (int pile : piles) {
totalHours += (pile + speed - 1) / speed;
}
return totalHours <= h;
}
public:
int minEatingSpeed(std::vector<int>& piles, int h) {
int left = 1;
int right = *std::max_element(piles.begin(), piles.end());
int result = right;
while (left <= right) {
int mid = left + (right - left) / 2;
if (canEatAll(piles, mid, h)) {
result = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return result;
}
};Complexity Analysis
- Time Complexity: O(n log m) where n is the number of piles and m is the maximum bananas count in a pile. The binary search takes log m steps, and each validation pass takes O(n) time.
- Space Complexity: O(1) auxiliary space as the search parameters are computed in place.
Where It Breaks
If h is very large (e.g. much larger than the total bananas), Koko can eat at speed 1. If h < piles.length, it is impossible to finish all piles, but the problem constraints ensure h >= piles.length.
Common Mistakes
- Integer Overflow: Using 32-bit integers to accumulate
totalHours. Ifpiles[i]is up to10^9and speed is small, the summation can overflow standard 32-bit registers. Usinglongin Java/C++ avoids this. - Ceiling Division Bug: Using simple division
pile / speedinstead of ceiling division. For example, if a pile has 5 bananas and speed is 3, Koko takes2hours to finish it (not1.66or1). Use(pile + speed - 1) / speedto compute the integer ceil directly.
Frequently Asked Questions
Why does Koko take a full hour even if the pile has fewer than k bananas? The rules state that she cannot move to another pile during the same hour, so she spends the rest of the hour resting.
Why does binary search work here? Because the relation between speed and hours is monotonic: as speed increases, the total hours needed to finish all bananas strictly decreases.