[LeetCode] 875 - Koko Eating Bananas

閱讀時間約 3 分鐘

Problem

給定一個有 n 堆香蕉的陣列 piles (第 i 堆的數量為 piles[i]),以及限時 h 小時,需要找出最少每小時需要吃的香蕉數量,才能在時限內把所有的香蕉吃完。

P.S. 每小時只能吃同一堆香蕉,因此就算那一堆剩餘的香蕉數量小於每小時吃的量,也無法跨堆去吃。

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

Solution

由於 piles 可能的組合太多,而且無法跨堆吃香蕉。因此,我們只能用窮舉的方式來找出答案,但要如何有效率的窮舉,是本題最大的考驗。

簡單整理關於窮舉的資訊:

  • 窮舉的範圍是在 [1, max(piles)] (因為題目保證 piles.length() <= h)
  • 假設每小時最少要吃的香蕉樹為 k,則 [1, k-1] 的數量都無法在時間內吃完全部香蕉,而 [k, max(piles)] 的數量都可以

有了範圍後,我們就不再是盲目地窮舉,而是搜尋。那講到搜尋,最常見有效、且容易實作的方法就是二分搜尋法 (binary search)。

一般的二分搜尋法,是根據數字大於或小於目標,來調整左界或右界。在此題中,我們則要根據每小時吃的香蕉數量 t,是否能在時限內吃完做調整:

  • 可以吃完 → 調整右界為 t (不是 t-1 的原因:不能保證每小時吃 t-1 個也能在時限內吃完,所以只能將右界縮減成確認過的 t 數量)
  • 無法吃完 → 調整左界為 t+1

判斷能否在時限內吃完,只需把每堆香蕉的數量 / t (記得要無條件進位喔),計算所需的小時數,再全部加起來。如果總時數符合時限內,則表示可以吃完。

整數除法 (無條件進位) 比較快速的方法

q = (x + y - 1) / y;
q = 1 + ((x - 1) / y); // if x != 0

Complexity

n 為 piles size

Time complexity: O(nlogn)

  • Binary search 總共會搜尋 logn 個數字 * 每個數字的檢查需要掃過整個 array O(n)O(nlongn)

Space complexity: O(1)

Code

class Solution {
public:
bool valid(vector<int> &piles, int h, int k) {
int hr = 0;
for (int p : piles) hr += (p + k - 1) / k;
return hr <= h;
}
int minEatingSpeed(vector<int>& piles, int h) {
int l = 1, r = 0;
for (int p : piles) r = max(p, r);

while (l < r) {
int m = (l + r) / 2;
if (valid(piles, h, m)) r = m;
else l = m + 1;
}

return r;
}
};

LeetCode Link

https://leetcode.com/problems/koko-eating-bananas/

1會員
1內容數
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
【LeetCode】19.Remove Nth Node From End of ListInput: head = [1,2,3,4,5], n = 2 Output: [1,2,3,5]
Thumbnail
avatar
2021-10-09
【LeetCode】876. Middle of the Linked ListInput: head = [1,2,3,4,5] Output: [3,4,5] 單看列表只是要找中間值,不過給定的資料結構不是陣列,而是鏈結串列。
Thumbnail
avatar
2021-10-09
【LeetCode】189. Rotate Array之前跳過的題目,回來補完成。 Input: nums = [1,2,3,4,5,6,7], k = 3 Output: [5,6,7,1,2,3,4]
Thumbnail
avatar
2021-10-08
【LeetCode】557. Reverse Words in a String III今日題目: 把一行字內每個單字都反轉字元。 Input: s = "Let's take LeetCode contest" Output: "s'teL ekat edoCteeL tsetnoc"
Thumbnail
avatar
2021-10-08
【LeetCode】344. Reverse String今日題目:字串反轉 Input: s = ["h","e","l","l","o"] Output: ["o","l","l","e","h"]
Thumbnail
avatar
2021-10-08
【LeetCode】167. Two Sum II 題目如下: Input: numbers = [2,7,11,15], target = 9 Output: [1,2]
Thumbnail
avatar
2021-10-07
【LeetCode】283. Move Zeroes題目要求如下: Input: nums = [0,1,0,3,12] Output: [1,3,12,0,0] 把0都搬到後面去,非0的數字移到前面,且不更改原本數字的大小順序。
Thumbnail
avatar
2021-10-07
【LeetCode】977. Squares of a Sorted Array比今天的題目示例如下: Input: nums = [-4,-1,0,3,10] Output: [0,1,9,16,100] 簡單來說,要的輸出結果是把陣列內每個數字取平方後,對陣列做排序。
Thumbnail
avatar
2021-10-06
【LeetCode】704. Binary SearchLeetcode上正好有14天的讀書計畫,今天三題都是二分搜索,順手三題都寫一寫,想法上很固定。
Thumbnail
avatar
2021-10-05
【LeetCode】20. Valid Parentheses 前幾天看別人直播刷題,心血來潮打開很久沒動的leetcode試試,挑了一題當初面試沒寫出來的題目。嗯...我那時才剛碰資料結構,知道要用stack寫卻沒實作過任何東西,現在有工作經驗後再來寫,看看會不會有不一樣的想法。
Thumbnail
avatar
2021-10-04