Koko Eating Bananas
Binary search the answer: eating speed is monotonic in whether she finishes in time.
Approach
The feasible speeds form a monotonic predicate — any speed fast enough works, slower ones don't. Binary search speeds between 1 and max(pile); for each candidate, sum the hours needed and check against h. Return the smallest feasible speed.
Time complexity
O(n log max)
Space complexity
O(1)
Common mistake
Searching values in the array instead of the answer space [1, max pile] — this is 'binary search on the answer'.
Interactive walkthrough — step through it below, free and without an account
Problem
Koko has several banana piles and can eat from only one pile during each hour. At a speed of k bananas per hour, she spends ceil(pile / k) hours on each pile. Return the smallest integer speed that allows her to finish all piles within h hours.
Examples
Input: piles = [3,6,7,11], h = 8
Output: 4
Input: piles = [30,11,23,4,20], h = 5
Output: 30
Problem
Problem
Koko has several banana piles and can eat from only one pile during each hour. At a speed of `k` bananas per hour, she spends `ceil(pile / k)` hours on each pile. Return the smallest integer speed that allows her to finish all piles within `h` hours.
Problem and Goal
Learning goal: Translate the eating process into a decision problem that can be searched efficiently.
Core idea
For a fixed speed k, each pile is independent. A pile of size p takes ceil(p / k) hours, so the total time is the sum of those rounded-up quotients. We need the smallest speed whose total time is at most h.
Decision version
Instead of asking directly for the answer, ask: "Can speed k finish all piles within h hours?"
Algorithm plan
- Choose a candidate speed
k. - Compute
hours = sum(ceil(pile / k)). - If
hours <= h, the speed works; try smaller speeds. - Otherwise, the speed is too slow; try larger speeds.
Micro-example
For piles = [3,6,7,11] and k = 4, the hours are 1 + 2 + 2 + 3 = 8. Since 8 <= h, speed 4 is feasible.
Pitfalls
- A pile that is not evenly divisible still needs a full final hour.
- The answer is a speed, not an index or an existing pile value.
- The goal is the minimum feasible speed, not merely any feasible speed.
Recap
- Test a speed with a total-hours calculation.
- Feasibility determines whether to move lower or higher.
- Minimize the speed while staying within the hour limit.
Problem and Goal
A speed is feasible if total hours fit
At speed `k = 4`, Koko needs `ceil(3/4) + ceil(6/4) + ceil(7/4) + ceil(11/4) = 8` hours.
Search for the first speed where feasibility becomes true.
The Monotonic Predicate
Learning goal: Recognize why binary search applies even though the piles themselves are not sorted.
Core idea As speed increases, the hours required for every pile can only stay the same or decrease. Therefore, feasibility has a monotonic shape: slow speeds fail, then all sufficiently fast speeds succeed. Binary search does not need sorted input values here; it needs a monotonic yes/no predicate over the candidate answers.
Key insight
The feasible speeds look like false, false, ..., true, true. Binary search locates the first true.
Algorithm plan
- Lower bound:
left = 1, because speed zero cannot make progress. - Upper bound:
right = max(piles), because this speed finishes the largest pile in one hour and is always sufficient whenh >= piles.length. - Let
midbe the candidate speed. - Keep the feasible half when
midworks; otherwise keep the faster half.
Micro-example
For [3,6,7,11], speeds 1, 2, and 3 fail for h = 8, while speed 4 and every faster speed succeed. The transition is between 3 and 4.
Pitfalls
- Do not search values in the array; the answer may be 4 even though 4 is not a pile size.
- The correct search space is every integer speed in
[1, max pile]. - Use a lower-bound style loop so the first feasible speed is retained.
Recap
- Feasibility is monotonic in speed.
- Search the answer space, not the input array.
- Return the leftmost feasible speed.
The Monotonic Predicate
If speed 4 works, every speed greater than 4 also works.
false before 4; true from 4 onward
Binary Search on the Answer
Learning goal: Build the complete binary-search algorithm and its feasibility calculation.
Core idea
The candidate speed is the value being searched. For each mid, calculate a pile's hours with integer arithmetic: ceil(pile / mid) equals (pile + mid - 1) // mid. If the total is within h, mid might be the answer, so move right left to search smaller speeds.
Algorithm plan
- Set
left = 1andright = max(piles). - While
left < right, computemid = (left + right) // 2. - Sum
(pile + mid - 1) // midfor every pile. - If the sum is at most
h, setright = mid; otherwise setleft = mid + 1. - Return
left.
while left < right:
mid = (left + right) // 2
hours = sum((p + mid - 1) // mid for p in piles)
if hours <= h:
right = mid
else:
left = mid + 1
return leftMicro-example
With bounds [1,11], mid = 6 needs 6 hours, so the answer is at most 6. The next candidate is tested in [1,5].
Pitfalls
- Do not use ordinary division without rounding up.
- Use
mid + 1after failure; the failed speed cannot be the answer. - Use a wide integer type for the hour sum in languages with fixed-width integers.
Recap
- A feasibility check costs
O(n). - Each binary-search step discards half the speed range.
- The final lower bound is the smallest feasible speed.
Binary Search on the Answer
Traces the concrete example `piles = [3,6,7,11]`, `h = 8` while searching speeds from 1 through 11.
Pitfalls and Edge Cases
Learning goal: Avoid the common boundary and interpretation errors in answer-space binary search.
Core idea
The input array does not define the sorted search domain. The possible answer is any integer speed from 1 through max(piles), including values that do not appear in piles. Correct bounds and ceiling division are the details that make the monotonic predicate reliable.
Algorithm plan
- Initialize the lower bound to 1, not 0.
- Initialize the upper bound to the largest pile.
- Count each pile with ceiling division.
- On feasibility, keep
midby assigningright = mid. - On failure, exclude
midwithleft = mid + 1.
Micro-example
For [3,6,7,11], searching only the pile values would examine [3,6,7,11] and could miss the true answer 4. The answer space [1,11] contains every possible speed.
Common pitfall
Searching values in the array instead of the answer space [1, max pile] is the wrong problem. This technique is called binary search on the answer.
Pitfalls
pile // kundercounts whenever a remainder exists.- If
h == piles.length, the answer ismax(piles). - A single pile works as a valid input, including when
his larger than one. - Do not return the first feasible
mid; continue searching left.
Recap
- Search speeds, not pile entries.
- Round every pile's hours upward.
- Preserve feasible
midvalues while narrowing to the minimum.
Pitfalls and Edge Cases
For `piles = [3,6,7,11]` and `h = 8`, which domain should binary search examine?
Complexity and Wrap-up
Learning goal: Explain the efficiency of the final solution and recognize the reusable pattern.
Core idea
Each feasibility check scans all n piles once, so it costs O(n). Binary search performs O(log max(piles)) checks because the speed interval is repeatedly halved. The implementation stores only a few variables beyond the input, giving constant auxiliary space.
Algorithm plan
- Define a monotonic predicate:
canFinish(k). - Search the integer answer range
[1, max(piles)]. - Keep a feasible midpoint as a possible answer.
- Remove failed speeds and return the collapsed lower bound.
Micro-example For the walkthrough, the range size is 11 and only three candidate checks are needed: speeds 6, 3, and 4. Each check scans the four piles.
Why it works
The predicate changes only once from false to true. Binary search finds that transition, so the returned speed is both feasible and minimal.
Pitfalls
- State the monotonic predicate before writing the loop.
- Distinguish
O(n log max(piles))fromO(n log n); the logarithm is over the answer range. - The result is a speed, not the number of hours or the largest pile.
Recap
- Time:
O(n log max(piles)). - Auxiliary space:
O(1). - The reusable pattern is binary search on a monotonic answer predicate.
Complexity and Wrap-up
Summarizes the cost of feasibility checks and the binary search over possible speeds.
Now try it on your own problem
Paste any LeetCode problem — or one of your own — and codebrew builds a walkthrough like this one for it.
Build a lesson from any problem
