Editorial
Core insight
Koko Eating Bananas · Binary Search Patterns
Core Insight for Koko Eating Bananas
The core insight that allows us to optimize the brute force approach is the monotonic relationship between the eating speed k and the total time required.
- Inverse Correlation: As the eating speed
kincreases, the total hours required decreases (or stays the same). - Search Space: The answer
kis bounded. The lower bound is 1, and the upper bound is the maximum element inpiles. - Feasibility Property:
- If Koko can finish with speed
x, she can definitely finish with speedx + 1. - If Koko cannot finish with speed
x, she definitely cannot finish with speedx - 1.
- If Koko can finish with speed
This monotonic property allows us to discard half of the search space at every step using Binary Search. We are looking for the leftmost value in the range [1, max(piles)] that satisfies the condition hours_needed <= h.
Visual Description:
Visualize the search space as a horizontal axis representing possible speeds k from 1 to max(piles). Above this axis, imagine a boolean function canFinish(k).
For small values of k, canFinish(k) is False (takes too long). At some specific threshold ans, the function flips to True and remains True for all subsequent values.
The binary search algorithm probes the midpoint. If canFinish(mid) is True, we know the answer is either mid or something to the left, so we eliminate the right half. If False, we know we must eat faster, so we eliminate the left half.
Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 875: Koko Eating Bananas Solution & Explanation
Problem Overview
TL;DR: We use binary search on the range of possible eating speeds to find the minimum integer speed k that allows Koko to finish all bananas within h hours.
In LeetCode 875, we are provided with an array of banana piles and a strict time limit h in hours. We must determine the minimum eating speed k (bananas per hour). The rules dictate that Koko can only eat from one pile per hour. If the pile size is less than k, she finishes the pile and waits for the next hour; she cannot move to another pile within the same hour. This creates a ceiling constraint on time consumption per pile.
The goal of the Koko Eating Bananas problem is to find the smallest integer k such that the sum of hours required for all piles is less than or equal to h.
Brute Force Approach for Koko Eating Bananas
The brute force approach involves checking every possible eating speed starting from the minimum possible speed.
- Start with
k = 1. - Calculate the total hours required to eat all bananas at speed
k. - If the total hours , return
k. - Otherwise, increment
kto 2, 3, etc., and repeat.
The maximum possible speed needed is the size of the largest pile (let's call this max(piles)), because eating faster than the pile size does not reduce the time spent on that specific pile (it always takes 1 hour minimum).
Pseudo-code:
max_speed = max(piles)
for k from 1 to max_speed:
hours_needed = 0
for pile in piles:
hours_needed += ceiling(pile / k)
if hours_needed <= h:
return kTime Complexity Analysis: The time complexity is , where is the number of piles and is the maximum number of bananas in a pile (). Given that can be up to , performing a linear scan is computationally infeasible and results in a Time Limit Exceeded (TLE) error. We need a logarithmic approach to search the solution space.
Algorithm Strategy: Binary Search Patterns
We utilize the standard "minimize k" binary search template.
-
Define Boundaries:
left: 1 (minimum possible speed).right: Maximum value inpiles(sufficient upper bound).
-
Condition Function (
canFinish):- For a given
mid(candidate speed), iterate throughpiles. - Calculate hours for each pile using integer math equivalent to ceiling:
(pile + mid - 1) / mid. - Sum these hours.
- Return
trueif the sum is .
- For a given
-
Binary Search Logic:
- While
left <= right:- Calculate
mid. - If
canFinish(mid)is true:- Record
midas a potential answer. - Try to find a smaller valid speed by moving
righttomid - 1.
- Record
- If
canFinish(mid)is false:- The speed is too slow. Move
lefttomid + 1.
- The speed is too slow. Move
- Calculate
- While
-
Result:
- The
leftpointer (or the variable storing the validmid) will correspond to the minimum speed.
- The
Execution Flow
Let's trace Example 1: piles = [3, 6, 7, 11], h = 8.
-
Initialization:
left= 1right= 11 (max of piles)
-
Iteration 1:
mid= (1 + 11) / 2 = 6.- Check(6):
- Pile 3: hr
- Pile 6: hr
- Pile 7: hrs
- Pile 11: hrs
- Total: hours.
- is True.
- Store
ans = 6. We might find a smaller speed. rightbecomes5.
-
Iteration 2:
left= 1,right= 5.mid= (1 + 5) / 2 = 3.- Check(3):
- Pile 3: 1 hr
- Pile 6: 2 hrs
- Pile 7: 3 hrs
- Pile 11: 4 hrs
- Total: 10 hours.
- is False.
- Speed 3 is too slow.
leftbecomes4.
-
Iteration 3:
left= 4,right= 5.mid= (4 + 5) / 2 = 4.- Check(4):
- Pile 3: 1 hr
- Pile 6: 2 hrs
- Pile 7: 2 hrs
- Pile 11: 3 hrs
- Total: 8 hours.
- is True.
- Store
ans = 4. rightbecomes3.
-
Termination:
left= 4,right= 3.- Loop terminates. Return
4.
Proof of Correctness
The correctness relies on the Monotonicity Property. The function is strictly non-increasing with respect to .
Because the function is monotonic, the boolean condition total_hours <= h splits the number line into two contiguous segments: [False, ..., False, True, ..., True].
Binary search is guaranteed to find the boundary between False and True in logarithmic time. Since we always store the valid mid and attempt to move left, the algorithm converges on the minimum k that satisfies the condition.
Pattern Reuse Notes
The "Binary Search on Answer" pattern used in LeetCode 875 is a fundamental technique for optimization problems where the answer lies within a range and satisfies a monotonic condition.
This same logic applies directly to:
- LeetCode 410: Split Array Largest Sum: Binary search the maximum subarray sum. The condition function checks if the array can be split into
msubarrays with that sum limit. - LeetCode 774: Minimize Max Distance to Gas Station: Binary search the distance. The condition checks if we can add
kstations to satisfy that distance. - LeetCode 1011: Capacity To Ship Packages Within D Days: Identical structure. Search for capacity
ksuch that packages are shipped inDdays. - LeetCode 1482: Minimum Number of Days to Make m Bouquets: Binary search the days. The condition checks if
mbouquets can be formed given the blooming status.
In all these cases, we replace the linear search of the answer space with binary search, reducing complexity from linear to logarithmic relative to the answer range.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 875
1class Solution {
2public:
3 int minEatingSpeed(vector<int>& piles, int h) {
4 int left = 1;
5 int right = 0;
6
7 // Determine the upper bound of the search space
8 for (int pile : piles) {
9 right = max(right, pile);
10 }
11
12 int result = right;
13
14 while (left <= right) {
15 int mid = left + (right - left) / 2;
16
17 // Calculate hours needed for speed 'mid'
18 long long hoursNeeded = 0;
19 for (int pile : piles) {
20 // Equivalent to ceil(pile / mid)
21 hoursNeeded += (pile + mid - 1) / mid;
22 }
23
24 if (hoursNeeded <= h) {
25 // Speed is sufficient, try to find a smaller speed
26 result = mid;
27 right = mid - 1;
28 } else {
29 // Speed is too slow, increase it
30 left = mid + 1;
31 }
32 }
33
34 return result;
35 }
36};Java Solution for LeetCode 875
1class Solution {
2 public int minEatingSpeed(int[] piles, int h) {
3 int left = 1;
4 int right = 0;
5
6 // Determine the upper bound
7 for (int pile : piles) {
8 right = Math.max(right, pile);
9 }
10
11 int result = right;
12
13 while (left <= right) {
14 int mid = left + (right - left) / 2;
15
16 long hoursNeeded = 0;
17 for (int pile : piles) {
18 // Integer arithmetic for ceil(pile / mid)
19 hoursNeeded += (pile + mid - 1) / mid;
20 }
21
22 if (hoursNeeded <= h) {
23 result = mid;
24 right = mid - 1;
25 } else {
26 left = mid + 1;
27 }
28 }
29
30 return result;
31 }
32}Python Solution for LeetCode 875
1import math
2
3class Solution:
4 def minEatingSpeed(self, piles: List[int], h: int) -> int:
5 left = 1
6 right = max(piles)
7
8 def can_finish(k):
9 hours_needed = 0
10 for pile in piles:
11 # Calculate ceiling of pile / k
12 hours_needed += (pile + k - 1) // k
13 return hours_needed <= h
14
15 while left <= right:
16 mid = (left + right) // 2
17
18 if can_finish(mid):
19 # Valid speed, try smaller
20 right = mid - 1
21 else:
22 # Too slow, need higher speed
23 left = mid + 1
24
25 return left