The problem
There are piles of bananas, and piles[i] is the size of pile i. Koko picks an eating speed k (bananas per hour). Each hour she chooses one pile and eats k bananas from it; if the pile has fewer than k, she finishes it and waits out the rest of the hour. Return the minimum integer k that lets her eat every banana within h hours. It is guaranteed that h >= len(piles).
Input: piles = [3, 6, 7, 11], h = 8
Output: 4At speed 4 the piles take 1, 2, 2 and 3 hours: 8 in total. At speed 3 they take 1, 2, 3 and 4: 10 hours, too slow.
How to think about it
Start with brute force. Try k = 1, 2, 3, … and return the first speed whose total time is at most h. Computing the time for one speed is O(n). Trying up to max(piles) speeds (up to 10⁹) makes this O(n · max), far too slow.
Look at how the answer to “is speed k fast enough?” behaves. If speed k works, any faster speed also works, because each pile takes the same or fewer hours. So across all speeds the answers look like no, no, no, yes, yes, yes. That is a monotonic yes/no sequence, and you want the first yes.
The key insight: binary-search the answer itself, not an array. The answer lies in [1, max(piles)]: speed max(piles) finishes every pile in one hour, which takes len(piles) <= h hours. For a candidate mid, compute the hours needed, sum(ceil(p / mid)). If it fits in h, mid works and the answer is mid or smaller (hi = mid); otherwise go faster (lo = mid + 1). That gives about 30 checks instead of a billion.
Which pattern is this? Search on the answer. The tell is a phrase like “minimum speed / capacity / size such that something is possible”, where checking one candidate is easy and feasibility is monotonic. It’s the same first-true template as First Bad Version, with the feasibility check playing the role of isBad.
Approach
- Set
lo = 1andhi = max(piles). - While
lo < hi:mid = (lo + hi) // 2.- Hours at speed
mid=sum(ceil(p / mid) for p in piles). - If hours
<= h, sethi = mid; else setlo = mid + 1.
- Return
lo.
Solution
import math
def min_eating_speed(piles, h):
lo, hi = 1, max(piles) # max(piles) always works
while lo < hi:
mid = (lo + hi) // 2
if sum(math.ceil(p / mid) for p in piles) <= h: hi = mid # fast enough: try slower
else: lo = mid + 1 # too slow
return lo
# min_eating_speed([3,6,7,11], 8) -> 4Dry run
On piles = [3, 6, 7, 11], h = 8:
| Step | lo |
hi |
mid |
Hours needed | Fits in 8? | Decision |
|---|---|---|---|---|---|---|
| 1 | 1 | 11 | 6 | 6 | yes | hi = 6 |
| 2 | 1 | 6 | 3 | 10 | no | lo = 4 |
| 3 | 4 | 6 | 5 | 8 | yes | hi = 5 |
| 4 | 4 | 5 | 4 | 8 | yes | hi = 4 |
Now lo == hi == 4, so the answer is 4.
Complexity
- Time: O(n log M), where
M = max(piles). The binary search takes O(log M) steps and each feasibility check sums over allnpiles. - Space: O(1). The generator inside
sumdoesn’t build a list.
Edge cases and pitfalls
h == len(piles): she must finish one pile per hour, so the answer ismax(piles).- Huge
h: the answer can be 1. Startloat 1, never 0, or you’ll divide by zero. - Ceiling division:
p // midundercounts. Usemath.ceil(p / mid)or the integer-only(p + mid - 1) // mid, which avoids float rounding for very large values. - Searching up to
sum(piles)still works but wastes steps.max(piles)is a tight upper bound.
Related problems
- Capacity To Ship Packages Within D Days (LeetCode 1011): search on the answer with a greedy day-packing check.
- Split Array Largest Sum (LeetCode 410): the same idea for “minimise the largest piece”.
- First Bad Version (LeetCode 278): the first-true template in its simplest form.
- 1.Binary Search (LeetCode 704)
- 2.Search Insert Position (LeetCode 35)
- 3.First Bad Version (LeetCode 278)
- 4.Search in Rotated Sorted Array (LeetCode 33)
- 5.Find Minimum in Rotated Sorted Array (LeetCode 153)
- 6.Find First and Last Position of Element in Sorted Array (LeetCode 34)
- 7.Search a 2D Matrix (LeetCode 74)
- 8.Find Peak Element (LeetCode 162)
- 9.Koko Eating Bananas (LeetCode 875)
- 10.Capacity To Ship Packages Within D Days (LeetCode 1011)
- 11.Time Based Key-Value Store (LeetCode 981)
- 12.Split Array Largest Sum (LeetCode 410)
- 13.Median of Two Sorted Arrays (LeetCode 4)