Hard草稿★★★★★O(n log n) 時間 · O(n) 空間
ArrayHeapPriority QueueSweep LineDivide and Conquer
Patterns🧹 差分・掃描線⛰️ 堆・Top-K✂️ 分治
尚未複習過

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

218The Skyline ProblemHeap / Priority QueueHardHeap / Priority Queue

給定一組建築 [left, right, height],輸出天際線的關鍵轉折點 [x, height]:每當「目前最高建築」的高度改變,就記錄一個點。

Example:

Input: buildings = [[2,9,10],[3,7,15],[5,12,12],[15,20,10],[19,24,8]] Output: [[2,10],[3,15],[7,12],[12,0],[15,10],[20,8],[24,0]]

Intuition

TIP

核心思路:掃描線 + 最大堆。把每棟建築拆成「進入」與「離開」兩個事件,沿 x 由左到右掃;用最大堆維護當前所有覆蓋此處的建築高度,堆頂改變時就產生一個關鍵點。

Approaches

⭐ Sweep Line + Max Heap (lazy deletion) — O(n log n) / O(n)
  • Idea: 事件驅動掃描,最大堆維護活躍高度,懶刪除離開的建築
  • Time: O(n log n) - 事件排序 + 堆操作
  • Space: O(n) - 事件、堆、刪除計數
import java.util.PriorityQueue

class Solution {
    fun getSkyline(buildings: Array<IntArray>): List<List<Int>> {
        val events = ArrayList<IntArray>()
        for (b in buildings) {
            events.add(intArrayOf(b[0], -b[2]))  // 進入:負高度
            events.add(intArrayOf(b[1], b[2]))    // 離開:正高度
        }
        // x 升序;同 x 依高度值升序(進入(負)在前、較高先處理)
        events.sortWith(compareBy({ it[0] }, { it[1] }))

        val result = ArrayList<List<Int>>()
        val heap = PriorityQueue<Int>(compareByDescending { it })  // 最大堆
        heap.add(0)
        val toRemove = HashMap<Int, Int>()
        var prevMax = 0
        for (e in events) {
            val x = e[0]
            if (e[1] < 0) {
                heap.add(-e[1])                                   // 進入
            } else {
                toRemove[e[1]] = (toRemove[e[1]] ?: 0) + 1         // 離開:延遲刪除
            }
            while (heap.isNotEmpty() && (toRemove[heap.peek()] ?: 0) > 0) {
                toRemove[heap.peek()] = toRemove[heap.peek()]!! - 1
                heap.poll()
            }
            val curMax = heap.peek() ?: 0
            if (curMax != prevMax) {
                result.add(listOf(x, curMax))
                prevMax = curMax
            }
        }
        return result
    }
}
Note: Divide & Conquer

也可像歸併排序一樣分治:把建築分兩半各自求天際線,再「合併兩條天際線」(類似合併兩個有序序列,逐點取較高者)。同為 O(n log n),合併階段是關鍵,思路接近 23 合併 K 條鏈結串列的合併概念。

🔑 Takeaways