The gateway to binary search on answer. The array doesn't contain the answer — the answer is a speed you binary search across all possible values.
Koko loves eating bananas. There are n piles of bananas, the i-th pile has piles[i] bananas. The guards will return in h hours. Koko can eat at most k bananas per hour. She eats one pile per hour and moves to the next. Return the minimum integer k such that she can eat all the bananas within h hours.
The key shift: we're not searching an array for a target. We're searching the space of possible speeds (1 to max(piles)) for the minimum speed that works. This is Binary Search on Answer.
Want to build this from first principles? Read the deeper intuition article for the brute-force solution, complexity breakdown, and the exact optimization leap to binary search.
If speed k works, speed k+1 also works. If speed k fails, speed k-1 also fails. This monotonic property is exactly what binary search needs.
For each pile, Koko needs ceil(pile / speed) hours. Sum all piles and check if total ≤ h. In code: (pile + speed - 1) / speed avoids floating point.
Search bounds: Minimum speed = 1 (always valid as a lower bound). Maximum speed = max(piles) — no point going faster since she can finish the biggest pile in 1 hour.
class Solution { public int minEatingSpeed(int[] piles, int h) { int left = 1; int right = 0; for (int p : piles) right = Math.max(right, p); int boundary = right; while (left <= right) { int mid = left + (right - left) / 2; if (canEat(piles, mid, h)) { boundary = mid; // works — try slower right = mid - 1; } else { left = mid + 1; // too slow — try faster } } return boundary; } private boolean canEat(int[] piles, int speed, int h) { int hours = 0; for (int pile : piles) hours += (pile + speed - 1) / speed; // ceiling division return hours <= h; } }
import math class Solution: def minEatingSpeed(self, piles: list[int], h: int) -> int: left, right = 1, max(piles) boundary = right while left <= right: mid = left + (right - left) // 2 if self.can_eat(piles, mid, h): boundary = mid right = mid - 1 else: left = mid + 1 return boundary def can_eat(self, piles, speed, h): return sum(math.ceil(p / speed) for p in piles) <= h