Binary search over the answer space to find the slowest eating rate that finishes in time.
Binary search on the answer: instead of searching for a value in an array, search for the minimum eating rate K in the range [1..max(piles)]. For each candidate rate, check whether Koko can finish all piles within the allotted hours. If yes, try a slower rate (hi = mid - 1); if not, eat faster (lo = mid + 1). The smallest feasible rate is the answer.
The key insight: the feasibility function is monotone. If rate K works, any rate > K also works. This means we can binary search on K in [1..max(piles)] rather than trying every rate linearly.
Start with lo=1 and hi=max(piles). At each step, pick mid=(lo+hi)/2, compute total hours needed at rate mid, then: if feasible (hours ≤ target), record mid as a candidate answer and try lower (hi=mid-1); otherwise eat faster (lo=mid+1).
For each of the O(log m) candidate rates (m = max pile), we spend O(n) computing the total hours. Overall: O(n log m) time, O(1) extra space (n = piles.length, m = max(piles)).
This "binary search on the answer" pattern applies to many problems where the feasibility function is monotone: ship packages within D days, split array largest sum, minimum days to make m bouquets, etc.