Medium草稿★★★★★O((m + n) * log n) 時間 · O(m) 空間
ArrayBinary SearchSorting
Patterns🎯 二分搜尋🔢 排序後處理
尚未複習過

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

2300Successful Pairs of Spells and PotionsBinary SearchMediumBinary Search

給定 spellspotions 兩個陣列以及一個整數 success。當 spells[i] * potions[j] >= success 時為成功配對。回傳每個 spell 的成功配對數量。

Example:

Input: spells = [5,1,3], potions = [1,2,3,4,5], success = 7 Output: [4,0,3]

Intuition

TIP

排序 potions 後,對每個 spell 二分搜尋找到最小的 potion 使乘積 >= success。

Approaches

1. Brute Force — O(m * n) / O(m)
  • Idea: 對每個 spell,遍歷所有 potions 計算成功配對數
  • Time: O(m * n)(m = spells 長度,n = potions 長度)
  • Space: O(m)(結果陣列)
Brute Force Code
class Solution {
    fun successfulPairs(spells: IntArray, potions: IntArray, success: Long): IntArray {
        return IntArray(spells.size) { i ->
            potions.count { p -> spells[i].toLong() * p >= success }
        }
    }
}
⭐ 2. Sort + Binary Search — O((m + n) * log n) / O(m)
  • Idea: 排序 potions,對每個 spell 二分搜尋第一個使乘積 >= success 的 potion 位置
  • Time: O((m + n) * log n)
  • Space: O(m)(結果陣列,不計排序空間)
class Solution {
    fun successfulPairs(spells: IntArray, potions: IntArray, success: Long): IntArray {
        potions.sort()
        val n = potions.size
        return IntArray(spells.size) { i ->
            val spell = spells[i].toLong()
            // 找第一個 potion 使得 spell * potion >= success
            var left = 0
            var right = n
            while (left < right) {
                val mid = left + (right - left) / 2
                if (spell * potions[mid] >= success) {
                    right = mid
                } else {
                    left = mid + 1
                }
            }
            n - left  // left 之後的所有 potion 都可以成功配對
        }
    }
}

WARNING

注意使用 Long 避免 spell * potion 溢位。n - left 就是從 left 位置到末尾的元素個數,即成功配對數。

🔑 Takeaways