Koko eating Banana || Return min value using Binary search

[Question]: There are n piles of bananas, the ith 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.

Example 1:

Input: piles = [3,6,7,11], h = 8
Output: 4

Example 2:

Input: piles = [30,11,23,4,20], h = 5
Output: 30
// TC: O(n log k)
//  O(n)(checkHours) * O(log k)(binary search where k = piles(max))
// SC: O(1) only a few integers are stored.

func checkHours(_ piles: [Int], _ k: Int, _ limit: Int) -> Bool {
     var hours = 0
     for pile in piles {
         hours += Int(ceil(Double(pile) / Double(k)))
         if hours > limit {// If hour limit exceeds means discard right half of array
             return false
         }
     }
     return hours <= limit
 }
 
 func minEatingSpeed(_ piles: [Int], _ h: Int) -> Int {
     // Define the binary search space,
     // 1...max(piles) in this case.
     var left = 1, right = Int.min
     for pile in piles {
         right = max(right, pile)
     }
     
     while left <= right {
         let mid = (left + right) / 2
         if checkHours(piles, mid, h) {
             // Koko eats too many bananas.
             // Encourage Koko to eat less bananas per hour.
             right = mid - 1
             // Discard right half of array
         } else {
             // Koko doesn't eat enough banans.
             // Ask Koko to eat one more banana per hour.
             left = mid + 1
             // Discard left half of array
         }
     }
     
     return left
 }
let v = [3,6,7,11]
let h = 8
let ans = minEatingSpeed(v, h)
print("Koko should eat at least ", ans, " bananas/hr.")// 4
#Approach 2: Using reduce
func minEatingSpeed1(_ piles: [Int], _ h: Int) -> Int {
    var (l, r) = (1, piles.max()!)
    while l < r{
        var k = (l + r) / 2
        let hrs = piles.reduce(0){return $0 + ($1 + k - 1)/k}
        (l, r) = hrs <= h ? (k-1, k) : (k+1, r)
    }
    return l
}

Leave a Comment

Your email address will not be published. Required fields are marked *