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 won't eat any more bananas during this hour.
Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back.
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
Example 3:
Input: piles = [30,11,23,4,20], H = 6
Output: 23
Note:
1 <= piles.length <= 10^4
piles.length <= H <= 10^9
1 <= piles[i] <= 10^9
這道題說有一只叫科科的猩猩,非常的喜歡吃香蕉,現在有N堆香蕉,每堆的個數可能不同,科科有H小時的時間來吃。要求是,每個小時內,科科只能選某一堆香蕉開始吃,若科科的吃速固定為K,即便在一小時內科科已經吃完了該堆的香蕉,也不能換堆,直到下一個小時才可以去另一堆吃。為了健康,科科想盡可能的吃慢一些,但同時也想在H小時內吃完所有的N堆香蕉,讓我們找出一個最小的吃速K值。那么首先來想,既然每個小時只能吃一堆,總共要在H小時內吃完N堆,那么H一定要大於等於N,不然一定沒法吃完N堆,這個條件題目中給了,所以就不用再 check 了。我們想一下K的可能的取值范圍,當H無窮大的時候,科科有充足的時間去吃,那么就可以每小時只吃一根,也可以吃完,所以K的最小取值是1。那么當H最小,等於N時,那么一個小時內必須吃完任意一堆,那么K值就應該是香蕉最多的那一堆的個數,題目中限定了不超過 1e9,這就是最大值。所以要求的K值的范圍就是 [1, 1e9],固定的范圍內查找數字,當然,最暴力的方法就是一個一個的試,憑博主多年與 OJ 抗衡的經驗來說,基本可以不用考慮的。那么二分查找法就是不二之選了,我們知道經典的二分查找法,是要求數組有序的,而這里香蕉個數數組又不一定是有序的。這是一個很好的觀察,但是要弄清楚到底是什么應該是有序的,要查找的K是吃速,跟香蕉堆的個數並沒有直接的關系,而K所在的數組其實應該是 [1, 1e9] 這個數組,其本身就是有序的,所以二分查找沒有問題。實際上這是博主之前那篇總結帖 [LeetCode Binary Search Summary 二分搜索法小結](https://www.cnblogs.com/grandyang/p/6854825.html) 中的第四類 - 用子函數當作判斷關系。當求出了 mid 之后,需要統計用該速度吃完所有的香蕉堆所需要的時間,統計的方法就是遍歷每堆的香蕉個數,然后算吃完該堆要的時間。比如 K=4,那么假如有3個香蕉,需要1個小時,有4香蕉,還是1個小時,有5個香蕉,就需要兩個小時,如果將三種情況融合為一個式子呢,就是用吃速加上香蕉個數減去1,再除以吃速即可,即 (pile+mid-1)/mid,大家可以自行帶數字檢驗,是沒有問題的。算出需要的總時間后去跟H比較,若小於H,說明吃的速度慢了,需要加快速度,所以 left 更新為 mid+1,否則 right 更新為 mid,最后返回 right 即可,參見代碼如下:
class Solution {
public:
int minEatingSpeed(vector<int>& piles, int H) {
int left = 1, right = 1e9;
while (left < right) {
int mid = left + (right - left) / 2, cnt = 0;
for (int pile : piles) cnt += (pile + mid - 1) / mid;
if (cnt > H) left = mid + 1;
else right = mid;
}
return right;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/875
類似題目:
Minimize Max Distance to Gas Station
參考資料:
https://leetcode.com/problems/koko-eating-bananas/
https://leetcode.com/problems/koko-eating-bananas/discuss/152324/C%2B%2BJavaPython-Binary-Search
[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)