AlgoMaster Logo

Koko Eating Bananas

Last Updated: April 1, 2026

medium
4 min read

Understanding the Problem

We need to find the minimum eating speed k that lets Koko finish all bananas within h hours. At speed k, each pile of size p takes ceil(p / k) hours to eat. The total hours across all piles must be at most h.

A couple of things to notice. First, increasing k can only decrease the total hours (or keep it the same). This means there's a clear threshold: every speed at or above some minimum value works, and everything below it doesn't. That monotonic property is the key. Second, Koko never moves on to a second pile in the same hour. Even if she finishes a pile early, the remaining time in that hour is wasted. So the total time is the sum of ceil(p / k) for each pile.

The question boils down to: what is the smallest k such that the sum of ceil(piles[i] / k) across all piles is at most h?

Key Constraints:

  • 1 <= piles.length <= 10^4 → Up to 10,000 piles. For each candidate speed, computing the total hours is O(n), which is fine.
  • piles.length <= h <= 10^9 → h is always at least the number of piles (Koko needs at least one hour per pile). h can be very large, which means very low speeds could work.
  • 1 <= piles[i] <= 10^9 → Pile sizes can be huge. The maximum possible speed we'd ever need is max(piles), since at that speed every pile takes exactly 1 hour.

Approach 1: Brute Force (Linear Search)

Intuition

The simplest idea: try every possible speed starting from 1, and for each speed, calculate how many hours Koko needs. Return the first speed where the total hours is at most h.

The speed range is [1, max(piles)]. At speed 1, every banana takes one hour, so the total is sum(piles), which is the maximum possible time. At speed max(piles), every pile takes at most 1 hour, so the total is n, which is the minimum possible time. Since h >= n, speed max(piles) always works, so we're guaranteed to find an answer.

For each candidate speed k, computing the total hours is straightforward: for each pile, the hours needed is ceil(piles[i] / k). A clean way to compute this without floating point is (piles[i] + k - 1) / k, which is the standard integer ceiling division trick.

Algorithm

  1. Find maxPile, the maximum value in piles.
  2. For each speed k from 1 to maxPile:
    • Compute totalHours = sum of ceil(piles[i] / k) for all piles.
    • If totalHours <= h, return k.
  3. Return maxPile (this line is technically unreachable since maxPile always works).

Example Walkthrough

1Start: try k=1. hours = ceil(3/1)+ceil(6/1)+ceil(7/1)+ceil(11/1) = 27. 27 > 8, too slow.
0
3
1
6
2
7
3
11
1/5

Code

The brute force tries every speed sequentially, but the feasibility function is monotonic. What if we could eliminate half the search range at each step instead?

Approach 2: Binary Search on Answer

Intuition

Here's the key insight that unlocks this problem: the feasibility of a speed is monotonic. If Koko can finish at speed k, she can definitely finish at any speed greater than k. If she can't finish at speed k, she can't finish at any speed less than k either. This is the classic setup for "binary search on the answer."

Instead of trying every speed one by one, we binary search over the range [1, max(piles)]. At each step, we pick the middle speed, check if it's feasible, and eliminate half the range. The feasibility check is simple: compute the total hours needed at that speed and compare with h.

The search finds the lower bound, the smallest speed where the total hours is at most h. This is the same lower bound binary search pattern used in problems like Search Insert Position, but instead of searching within an array, we're searching over an abstract answer space.

Algorithm

  1. Set left = 1 and right = max(piles).
  2. While left < right:
    • Compute mid = left + (right - left) / 2.
    • Calculate totalHours = sum of ceil(piles[i] / mid) for all piles.
    • If totalHours <= h, this speed works, but there might be a slower speed that also works. Set right = mid.
    • Otherwise, this speed is too slow. Set left = mid + 1.
  3. Return left.

Example Walkthrough

1Initialize: search range [1, 11], left=1, right=11
0
3
1
6
2
7
3
11
1/6

Code