Taro Logo

Koko Eating Bananas

Medium
Apple logo
Apple
2 views
Topics:
ArraysBinary Search

Koko loves to eat bananas. There are n piles of bananas, the i-th pile has piles[i] bananas. The guards have gone and will come back in h hours.

Koko can decide her bananas-per-hour eating speed of k. Each hour, she chooses some pile of bananas and eats k bananas from that pile. If the pile has less than k bananas, she eats all of them instead and will not eat any more bananas during this hour.

Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.

Return the minimum integer k such that she can eat all the bananas within h hours.

For example:

  • piles = [3,6,7,11], h = 8 The output should be 4.
  • piles = [30,11,23,4,20], h = 5 The output should be 30
  • piles = [30,11,23,4,20], h = 6 The output should be 23

Can you devise an efficient algorithm to determine the minimum eating speed k?

Solution


Koko Eating Bananas Problem Solution

Here's how we can solve the Koko eating bananas problem efficiently.

1. Naive Approach (Brute Force)

A simple, but inefficient, way to solve this problem is to iterate through all possible values of k (bananas per hour) starting from 1, and check if Koko can eat all the bananas within h hours for each k. The first k that satisfies the condition is the minimum k we are looking for.

Algorithm:

  1. Start with k = 1.
  2. For each k, calculate the total hours needed to eat all bananas.
  3. If the total hours are less than or equal to h, return k.
  4. Increment k and repeat steps 2 and 3.

Code (Python):

def can_eat_all(piles, h, k):
    hours = 0
    for pile in piles:
        hours += (pile + k - 1) // k  # Ceil division
    return hours <= h

def min_eating_speed_brute_force(piles, h):
    k = 1
    while True:
        if can_eat_all(piles, h, k):
            return k
        k += 1

Big O Analysis:

  • Time Complexity: O(K * N), where K is the minimum eating speed and N is the number of piles. In the worst case, K can be as large as the largest pile.
  • Space Complexity: O(1)

2. Optimal Approach (Binary Search)

We can use binary search to find the optimal value of k. The minimum possible value of k is 1, and the maximum possible value of k is the largest pile size. We can perform a binary search within this range to find the minimum k that satisfies the condition.

Algorithm:

  1. Initialize left = 1 and right = max(piles).
  2. While left < right:
    • Calculate mid = left + (right - left) // 2 (to prevent overflow).
    • Calculate the total hours needed to eat all bananas with speed mid.
    • If the total hours are less than or equal to h, it means mid might be a valid answer, so we try to reduce k further by setting right = mid.
    • Otherwise, if the total hours are greater than h, it means mid is too small, so we increase k by setting left = mid + 1.
  3. Return left (or right, since left == right at the end).

Code (Python):

def can_eat_all(piles, h, k):
    hours = 0
    for pile in piles:
        hours += (pile + k - 1) // k  # Ceil division
    return hours <= h

def min_eating_speed(piles, h):
    left, right = 1, max(piles)
    while left < right:
        mid = left + (right - left) // 2
        if can_eat_all(piles, h, mid):
            right = mid
        else:
            left = mid + 1
    return left

Big O Analysis:

  • Time Complexity: O(N * log(M)), where N is the number of piles and M is the maximum value in piles. This is because we perform a binary search between 1 and the maximum pile size, and for each mid value, we iterate through all the piles to calculate the total hours.
  • Space Complexity: O(1)

3. Edge Cases

  • piles is empty: The problem statement says 1 <= piles.length <= 10^4, so this case is not possible.
  • h is very small (close to the number of piles): This forces k to be large. The binary search handles this case efficiently.
  • h is very large: This allows k to be small. The binary search also handles this case without issues.
  • Overflow in calculating hours: The intermediate hours value could become large, but since we are only comparing it with h (which is at most 10^9), we do not need to worry about integer overflow issues assuming we are using a 64 bit integer.