Hard草稿★★★★★O(n * log(maxVal) * log n) 時間 · O(n) 空間
HeapPriority QueueGreedyOrdered Set
Patterns🏗️ 資料結構設計⛰️ 堆・Top-K🪙 貪心
尚未複習過

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

1675Minimize Deviation in ArrayHeap / Priority QueueHardHeap / Priority Queue

給定一個正整數陣列 nums,你可以對任意元素執行以下操作任意次:若元素為偶數,可以除以 2;若元素為奇數,可以乘以 2。求陣列中最大值與最小值之差(deviation)的最小可能值。

Example:

Input: nums = [1,2,3,4] Output: 1

Intuition

TIP

核心思路:先把所有數都變成最大值(奇數乘 2),然後用 Max Heap 不斷縮小最大值,追蹤最小 deviation。

Approaches

1. TreeSet (min & max together) — O(n · log(maxVal) · log n) / O(n)
  • Idea: 與堆解同邏輯,改用 TreeSet 一個結構同時 O(log n) 取最大與最小,程式更簡潔
  • Time: O(n · log(maxVal) · log n)
  • Space: O(n)
class Solution {
    fun minimumDeviation(nums: IntArray): Int {
        val set = java.util.TreeSet<Int>()
        for (x in nums) set.add(if (x % 2 == 1) x * 2 else x)   // 奇數先 *2
        var res = set.last() - set.first()
        while (set.last() % 2 == 0) {        // 最大是偶數才能再 /2 變小
            val max = set.pollLast()
            set.add(max / 2)
            res = minOf(res, set.last() - set.first())
        }
        return res
    }
}
⭐ 2. Max Heap + Greedy — O(n * log(maxVal) * log n) / O(n)
  • Idea: 將所有奇數先乘 2 推入 Max Heap,追蹤最小值。每次取出最大值,若為偶數則除以 2 後放回,更新 deviation
  • Time: O(n * log(maxVal) * log n) - 每個元素最多被除 log(maxVal) 次,每次 heap 操作 O(log n)
  • Space: O(n)
class Solution {
    fun minimumDeviation(nums: IntArray): Int {
        val maxHeap = PriorityQueue<Int>(compareByDescending { it })
        var minVal = Int.MAX_VALUE

        for (num in nums) {
            val val_ = if (num % 2 == 1) num * 2 else num
            maxHeap.offer(val_)
            minVal = minOf(minVal, val_)
        }

        var result = maxHeap.peek() - minVal

        while (maxHeap.peek() % 2 == 0) {
            val maxVal = maxHeap.poll()
            val halved = maxVal / 2
            maxHeap.offer(halved)
            minVal = minOf(minVal, halved)
            result = minOf(result, maxHeap.peek() - minVal)
        }

        return result
    }
}

🔑 Takeaways