Koko Eating Bananas
You are given an array arr[]
of n
integers, where each element represents a pile of bananas. Koko has k
hours to finish all the piles, and it's guaranteed that n ≤ k
. Your task is to find the minimum number of bananas per hour, x
, that Koko must eat to finish all the bananas within k
hours.
Each hour, Koko can choose any pile and eat up to x
bananas from it. If a pile has x
or fewer bananas, she eats the whole pile in that hour.
Examples:
Input: arr[] = [5, 10, 3], k = 4
Output: 5
Explanation: If Koko eats at the rate of 5 bananas per hour:
- First pile of 5 bananas will be finished in 1 hour.
- Second pile of 10 bananas will be finished in 2 hours.
- Third pile of 3 bananas will be finished in 1 hours.
Therefore, Koko can finish all piles of bananas in 1 + 2 + 1 = 4 hours.
Input: arr[] = [5, 10, 15, 20], k = 7
Output: 10
Explanation: If Koko eats at the rate of 10 bananas per hour, it will take 6 hours to finish all the piles.
Table of Content
[Naive Approach] Using Linear Search - O(n * m) time and O(1) space
The idea is to evaluate each possible speed, starting from 1, and calculate the total time needed for Koko to eat all the bananas at that speed. The minimum speed at which the total eating time is less than or equal to k hours is our answer. In this way, Koko eats all the bananas within the allowed time at the slowest possible pace.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Function to find the minimum eating speed to finish bananas within k hours
int kokoEat(vector<int>& arr, int k) {
int mx = *max_element(arr.begin(), arr.end());
for (int speed = 1; speed <= mx; speed++) {
long long time = 0;
for (int i = 0; i < arr.size(); i++) {
// Add the time needed to eat this pile at the current speed
time += arr[i] / speed;
if (arr[i] % speed != 0) {
// Extra hour for remaining bananas
time++;
}
}
// If total time is within allowed hours, return this speed
if (time <= k) {
return speed;
}
}
// If no smaller speed works, return the max pile size
return mx;
}
// Driver code
int main() {
vector<int> arr = {5, 10, 3};
int k = 4;
int minSpeed = kokoEat(arr, k);
cout << minSpeed << endl;
return 0;
}
import java.util.Arrays;
class GfG {
static int kokoEat(int[] arr, int k) {
int mx = Arrays.stream(arr).max().getAsInt();
for (int speed = 1; speed <= mx; speed++) {
long time = 0;
for (int i = 0; i < arr.length; i++) {
// Time required to eat this pile
// of bananas at current speed
time += arr[i] / speed;
// 1 extra hour to eat the remainder
// number of bananas in this pile
if (arr[i] % speed != 0) {
time++;
}
}
// If total eating time at current speed
// is smaller than given time
if (time <= k) {
return speed;
}
}
return mx;
}
public static void main(String[] args) {
int[] arr = {5, 10, 3};
int k = 4;
System.out.println(kokoEat(arr, k));
}
}
def kokoEat(arr, k):
mx = max(arr)
for speed in range(1, mx + 1):
time = 0
for i in range(len(arr)):
# Time required to eat this pile
# of bananas at current speed
time += arr[i] // speed
# 1 extra hour to eat the remainder
# number of bananas in this pile
if arr[i] % speed != 0:
time += 1
# If total eating time at current speed
# is smaller than given time
if time <= k:
return speed
return mx
if __name__ == "__main__":
arr = [5, 10, 3]
k = 4
print(kokoEat(arr, k))
using System;
using System.Linq;
class GfG {
static int kokoEat(int[] arr, int k) {
int mx = arr.Max();
for (int speed = 1; speed <= mx; speed++) {
long time = 0;
for (int i = 0; i < arr.Length; i++) {
// Time required to eat this pile
// of bananas at current speed
time += arr[i] / speed;
// 1 extra hour to eat the remainder
// number of bananas in this pile
if (arr[i] % speed != 0) {
time++;
}
}
// If total eating time at current speed
// is smaller than given time
if (time <= k) {
return speed;
}
}
return mx;
}
static void Main() {
int[] arr = {5, 10, 3};
int k = 4;
Console.WriteLine(kokoEat(arr, k));
}
}
function kokoEat(arr, k) {
let mx = Math.max(...arr);
for (let speed = 1; speed <= mx; speed++) {
let time = 0;
for (let i = 0; i < arr.length; i++) {
// Time required to eat this pile
// of bananas at current speed
time += Math.floor(arr[i] / speed);
// 1 extra hour to eat the remainder
// number of bananas in this pile
if (arr[i] % speed !== 0) {
time++;
}
}
// If total eating time at current speed
// is smaller than given time
if (time <= k) {
return speed;
}
}
return mx;
}
let arr = [5, 10, 3];
let k = 4;
console.log(kokoEat(arr, k));
Output
5
Time Complexity: O(n * m), where m is maximum bananas among all piles.
Auxiliary Space: O(1)
[Expected Approach] Using Binary Search - O(n * log m) time and O(1) space
The idea is to solve the problem by applying binary search on answer.
- Lower limit of speed is 1 banana/hr as Koko must eat at least one banana per hour, and Upper limit is the maximum bananas among all piles.
- Apply binary search on the possible answer range to get minimum speed to eat all bananas within k hours.
- If the current speed (mid) is enough to eat all bananas within given k hours then update the minimum eating time and continue the search in lower half of the range to check for slower eating speeds.
- Else search in upper half of the range as we need to increase the eating speed.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// Function to check whether current speed is enough
bool check(vector<int>& arr, int mid, int k) {
int hours = 0;
for (int i = 0; i < arr.size(); i++) {
hours += arr[i] / mid;
// Add one more hour if some bananas are left
if (arr[i] % mid != 0) {
hours++;
}
}
// Return true if total hours needed is within limit
return hours <= k;
}
// Function to find the minimum eating speed
int kokoEat(vector<int>& arr, int k) {
int lo = 1;
int hi = *max_element(arr.begin(), arr.end());
int res = hi;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (check(arr, mid, k)) {
// Update result and try slower speed
res = mid;
hi = mid - 1;
} else {
// Need faster speed
lo = mid + 1;
}
}
return res;
}
int main() {
vector<int> arr = {5, 10, 3};
int k = 4;
cout << kokoEat(arr, k) << endl;
return 0;
}
import java.util.Arrays;
class GfG {
// Function to check whether mid speed is enough
// to eat all piles of bananas under k hours
static boolean check(int[] arr, int mid, int k) {
int hours = 0;
for (int i = 0; i < arr.length; i++) {
hours += arr[i] / mid;
// 1 extra hour to eat the remainder
// number of bananas in this pile
if (arr[i] % mid != 0) {
hours++;
}
}
// return true if required time is less than
// or equals to given hour, otherwise return false
return hours <= k;
}
static int kokoEat(int[] arr, int k) {
// Minimum speed of eating is 1 banana/hours
int lo = 1;
// Maximum speed of eating is
// the maximum bananas in given piles
int hi = Arrays.stream(arr).max().getAsInt();
int res = hi;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
// Check if the mid(hours) is valid
if (check(arr, mid, k) == true) {
// If valid continue to search at
// lower speed
hi = mid - 1;
res = mid;
}
else {
// If cant finish bananas in given
// hours, then increase the speed
lo = mid + 1;
}
}
return res;
}
public static void main(String[] args) {
int[] arr = {5, 10, 3};
int k = 4;
System.out.println(kokoEat(arr, k));
}
}
# Function to check whether mid speed is enough
# to eat all piles of bananas under k hours
def check(arr, mid, k):
hours = 0
for i in range(len(arr)):
hours += arr[i] // mid
# 1 extra hour to eat the remainder
# number of bananas in this pile
if arr[i] % mid != 0:
hours += 1
# return true if required time is less than
# or equals to given hour, otherwise return false
return hours <= k
def kokoEat(arr, k):
# Minimum speed of eating is 1 banana/hours
lo = 1
# Maximum speed of eating is
# the maximum bananas in given piles
hi = max(arr)
res = hi
while lo <= hi:
mid = lo + (hi - lo) // 2
# Check if the mid(hours) is valid
if check(arr, mid, k) == True:
# If valid continue to search at
# lower speed
hi = mid - 1
res = mid
else:
# If cant finish bananas in given
# hours, then increase the speed
lo = mid + 1
return res
if __name__ == "__main__":
arr = [5, 10, 3]
k = 4
print(kokoEat(arr, k))
using System;
using System.Linq;
class GfG {
// Function to check whether mid speed is enough
// to eat all piles of bananas under k hours
static bool check(int[] arr, int mid, int k) {
int hours = 0;
for (int i = 0; i < arr.Length; i++) {
hours += arr[i] / mid;
// 1 extra hour to eat the remainder
// number of bananas in this pile
if (arr[i] % mid != 0) {
hours++;
}
}
// return true if required time is less than
// or equals to given hour, otherwise return false
return hours <= k;
}
static int kokoEat(int[] arr, int k) {
// Minimum speed of eating is 1 banana/hours
int lo = 1;
// Maximum speed of eating is
// the maximum bananas in given piles
int hi = arr.Max();
int res = hi;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
// Check if the mid(hours) is valid
if (check(arr, mid, k) == true) {
// If valid continue to search at
// lower speed
hi = mid - 1;
res = mid;
}
else {
// If cant finish bananas in given
// hours, then increase the speed
lo = mid + 1;
}
}
return res;
}
static void Main() {
int[] arr = {5, 10, 3};
int k = 4;
Console.WriteLine(kokoEat(arr, k));
}
}
// Function to check whether mid speed is enough
// to eat all piles of bananas under k hours
function check(arr, mid, k) {
let hours = 0;
for (let i = 0; i < arr.length; i++) {
hours += Math.floor(arr[i] / mid);
// 1 extra hour to eat the remainder
// number of bananas in this pile
if (arr[i] % mid !== 0) {
hours++;
}
}
// return true if required time is less than
// or equals to given hour, otherwise return false
return hours <= k;
}
function kokoEat(arr, k) {
// Minimum speed of eating is 1 banana/hours
let lo = 1;
// Maximum speed of eating is
// the maximum bananas in given piles
let hi = Math.max(...arr);
let res = hi;
while (lo <= hi) {
let mid = lo + Math.floor((hi - lo) / 2);
// Check if the mid(hours) is valid
if (check(arr, mid, k) === true) {
// If valid continue to search at
// lower speed
hi = mid - 1;
res = mid;
}
else {
// If cant finish bananas in given
// hours, then increase the speed
lo = mid + 1;
}
}
return res;
}
let arr = [5, 10, 3];
let k = 4;
console.log(kokoEat(arr, k));
Output
5
Time Complexity: O(n log m), where m is the max bananas from all piles.
Auxiliary Space: O(1)