Open In App

Koko Eating Bananas

Improve
Improve
Like Article
Like
Save
Share
Report

Given N piles of bananas, the ith pile has piles[i] bananas and H hours time until guards return (N < H). Find the minimum (S) bananas to eat per hour such that Koko can eat all the bananas within H hours. Each hour, Koko chooses some pile of bananas and eats S bananas from that pile. If the pile has less than S bananas, then she consumes all of them, and won’t eat any more bananas during that hour. 

Examples:

Input: piles = [3, 6, 7, 11], H = 8
Output: 4
Explanation:  Koko will eat 4 bananas per hour to finish all the bananas

Input: piles = [30, 11, 23, 4, 20], H = 6
Output: 23
Explanation:  Koko will eat 23 bananas per hour to finish all the bananas

 

Naive Approach: Koko must eat at least one banana per hour. Let lower bound be start. The maximum number of bananas Koko can eat in one hour is the maximum number of bananas from all piles. This is the maximum possible value of S. Let upper bound ends. Having search interval from start to end and using linear search, for every value of S, it can be checked if this speed of eating bananas is valid or not. The first valid value of S will be the slowest speed and the desired answer.

Time Complexity: O(N * W), where W is maximum bananas from all piles 

Approach: Given problem can be solved efficiently by using binary search on answer technique:

  • Create a boolean function to check if the chosen speed (bananas/hour) is enough to eat all bananas within given H hours time or not
  • Lower limit of S is 1 banana/hr as Koko must eat one banana per hour, and Upper limit is the maximum bananas of all piles
  • Apply binary search on the possible answer range to get minimum value of S
    • If the boolean function satisfies the mid value reduce higher to mid
    • Else update lower limit to mid + 1

C++




// C++ implementation for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
bool check(vector<int>& bananas, int mid_val, int H)
{
    int time = 0;
    for (int i = 0; i < bananas.size(); i++) {
 
        // to get the ceil value
        if (bananas[i] % mid_val != 0) {
 
            // in case of odd number
            time += ((bananas[i] / mid_val) + 1);
        }
        else {
 
            // in case of even number
            time += (bananas[i] / mid_val);
        }
    }
 
    // check if time is less than
    // or equals to given hour
    if (time <= H) {
        return true;
    }
    else {
        return false;
    }
}
 
int minEatingSpeed(vector<int>& piles, int H)
{
 
    // as minimum speed of eating must be 1
    int start = 1;
 
    // Maximum speed of eating
    // is the maximum bananas in given piles
    int end = *max_element(piles.begin(), piles.end());
 
    while (start < end) {
        int mid = start + (end - start) / 2;
 
        // Check if the mid(hours) is valid
        if ((check(piles, mid, H)) == true) {
 
            // If valid continue to search
            // lower speed
            end = mid;
        }
        else {
            // If cant finish bananas in given
            // hours, then increase the speed
            start = mid + 1;
        }
    }
    return end;
}
 
// Driver code
int main()
{
    vector<int> piles = { 30, 11, 23, 4, 20 };
    int H = 6;
    cout << minEatingSpeed(piles, H);
    return 0;
}


Java




// Java implementation for the above approach
 
 
import java.util.*;
 
class GFG{
 
static boolean check(int[] bananas, int mid_val, int H)
{
    int time = 0;
    for (int i = 0; i < bananas.length; i++) {
 
        // to get the ceil value
        if (bananas[i] % mid_val != 0) {
 
            // in case of odd number
            time += ((bananas[i] / mid_val) + 1);
        }
        else {
 
            // in case of even number
            time += (bananas[i] / mid_val);
        }
    }
 
    // check if time is less than
    // or equals to given hour
    if (time <= H) {
        return true;
    }
    else {
        return false;
    }
}
 
static int minEatingSpeed(int []piles, int H)
{
 
    // as minimum speed of eating must be 1
    int start = 1;
 
    // Maximum speed of eating
    // is the maximum bananas in given piles
    int end = Arrays.stream(piles).max().getAsInt();
 
    while (start < end) {
        int mid = start + (end - start) / 2;
 
        // Check if the mid(hours) is valid
        if ((check(piles, mid, H)) == true) {
 
            // If valid continue to search
            // lower speed
            end = mid;
        }
        else {
            // If cant finish bananas in given
            // hours, then increase the speed
            start = mid + 1;
        }
    }
    return end;
}
 
// Driver code
public static void main(String[] args)
{
    int []piles = { 30, 11, 23, 4, 20 };
    int H = 6;
    System.out.print(minEatingSpeed(piles, H));
}
}
 
// This code is contributed by 29AjayKumar


Python3




# Python implementation for the above approach
def check(bananas, mid_val, H):
  time = 0;
  for i in range(len(bananas)):
     
    # to get the ceil value
    if (bananas[i] % mid_val != 0):
       
      # in case of odd number
      time += bananas[i] // mid_val + 1;
    else:
       
      # in case of even number
      time += bananas[i] // mid_val
 
  # check if time is less than
  # or equals to given hour
  if (time <= H):
    return True;
  else:
    return False;
   
def minEatingSpeed(piles, H):
  # as minimum speed of eating must be 1
  start = 1;
 
  # Maximum speed of eating
  # is the maximum bananas in given piles
  end = sorted(piles.copy(), reverse=True)[0]
 
  while (start < end):
    mid = start + (end - start) // 2;
 
    # Check if the mid(hours) is valid
    if (check(piles, mid, H) == True):
       
      # If valid continue to search
      # lower speed
      end = mid;
    else:
       
      # If cant finish bananas in given
      # hours, then increase the speed
      start = mid + 1;
  return end;
 
# Driver code
piles = [30, 11, 23, 4, 20];
H = 6;
print(minEatingSpeed(piles, H));
 
# This code is contributed by gfgking.


C#




// C# implementation for the above approach
using System;
using System.Linq;
public class GFG{
 
static bool check(int[] bananas, int mid_val, int H)
{
    int time = 0;
    for (int i = 0; i < bananas.Length; i++) {
 
        // to get the ceil value
        if (bananas[i] % mid_val != 0) {
 
            // in case of odd number
            time += ((bananas[i] / mid_val) + 1);
        }
        else {
 
            // in case of even number
            time += (bananas[i] / mid_val);
        }
    }
 
    // check if time is less than
    // or equals to given hour
    if (time <= H) {
        return true;
    }
    else {
        return false;
    }
}
 
static int minEatingSpeed(int []piles, int H)
{
 
    // as minimum speed of eating must be 1
    int start = 1;
 
    // Maximum speed of eating
    // is the maximum bananas in given piles
    int end = piles.Max();
 
    while (start < end) {
        int mid = start + (end - start) / 2;
 
        // Check if the mid(hours) is valid
        if ((check(piles, mid, H)) == true) {
 
            // If valid continue to search
            // lower speed
            end = mid;
        }
        else {
            // If cant finish bananas in given
            // hours, then increase the speed
            start = mid + 1;
        }
    }
    return end;
}
 
// Driver code
public static void Main(String[] args)
{
    int []piles = { 30, 11, 23, 4, 20 };
    int H = 6;
    Console.Write(minEatingSpeed(piles, H));
}
}
 
// This code is contributed by shikhasingrajput


Javascript




<script>
// Javascript implementation for the above approach
 
function check(bananas, mid_val, H) {
  let time = 0;
  for (let i = 0; i < bananas.length; i++) {
    // to get the ceil value
    if (bananas[i] % mid_val != 0) {
      // in case of odd number
      time += Math.floor(bananas[i] / mid_val) + 1;
    } else {
      // in case of even number
      time += Math.floor(bananas[i] / mid_val);
    }
  }
 
  // check if time is less than
  // or equals to given hour
  if (time <= H) {
    return true;
  } else {
    return false;
  }
}
 
function minEatingSpeed(piles, H) {
  // as minimum speed of eating must be 1
  let start = 1;
 
  // Maximum speed of eating
  // is the maximum bananas in given piles
  let end = [...piles].sort((a, b) => b - a)[0];
 
  while (start < end) {
    let mid = start + Math.floor((end - start) / 2);
 
    // Check if the mid(hours) is valid
    if (check(piles, mid, H) == true) {
      // If valid continue to search
      // lower speed
      end = mid;
    } else {
      // If cant finish bananas in given
      // hours, then increase the speed
      start = mid + 1;
    }
  }
  return end;
}
 
// Driver code
 
let piles = [30, 11, 23, 4, 20];
let H = 6;
document.write(minEatingSpeed(piles, H));
 
</script>


 
 

Output

23

 

Time Complexity:  O(N log W) (W is the max bananas from all piles)
Auxiliary Space: O(1)

 



Last Updated : 27 Oct, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments