Medium草稿★★★★O(n * log(max(piles))) 時間 · O(1) 空間
ArrayBinary Search
Patterns📐 二分答案🎯 二分搜尋
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

875Koko Eating BananasBinary SearchMediumBinary Search

Koko 有 n 堆香蕉,第 i 堆有 piles[i] 根。守衛會在 h 小時後回來。Koko 每小時吃速度為 k 根(每堆吃完才換下一堆,不足 k 根的那堆也算一小時)。求最小的 k 使得她能在 h 小時內吃完所有香蕉。

Example:

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

Intuition

TIP

在答案空間 [1, max(piles)] 上二分搜尋,找到最小的吃速 k 使得總時間不超過 h。

Approaches

1. Linear Search — O(max(piles) * n) / O(1)
  • Idea: 從 k=1 開始逐一嘗試,直到找到第一個能在 h 小時內吃完的速度
  • Time: O(max(piles) * n)
  • Space: O(1)
Linear Search Code
class Solution {
    fun minEatingSpeed(piles: IntArray, h: Int): Int {
        for (k in 1..piles.max()) {
            var hours = 0L
            for (p in piles) {
                hours += (p + k - 1) / k
            }
            if (hours <= h) return k
        }
        return piles.max()
    }
}
⭐ 2. Binary Search on Answer Space — O(n * log(max(piles))) / O(1)
  • Idea: 在 [1, max(piles)] 的答案空間上二分搜尋最小可行的 k
  • Time: O(n * log(max(piles)))
  • Space: O(1)
class Solution {
    fun minEatingSpeed(piles: IntArray, h: Int): Int {
        var left = 1
        var right = piles.max()
        while (left < right) {
            val mid = left + (right - left) / 2
            var hours = 0L
            for (p in piles) {
                hours += (p + mid - 1) / mid
            }
            if (hours <= h) {
                right = mid
            } else {
                left = mid + 1
            }
        }
        return left
    }
}

WARNING

計算總時間時要用 Long 避免溢位。向上取整的技巧:(p + k - 1) / k 等同於 ceil(p / k)

🔑 Takeaways

Ladders 看全部 →

🎯

二分搜尋「答案」

答案具單調性時,對答案值域二分。

  1. 1
  2. 2#1011Capacity to Ship Packages Within D DaysMedium對每日載重二分
  3. 3#410Split Array Largest SumHard對「最大子陣列和」二分 + 貪心驗證