📏 Intervals

排序後合併、插入與重疊判斷。

8 題

📖 分類導讀

區間問題通常需要排序後處理重疊、合併或插入。常見技巧包括按起點排序和掃描線演算法。

Notes:

  • 大多數區間題的第一步是按起點排序
  • 判斷重疊:a.end >= b.start(排序後)
  • 合併區間和插入區間是最基本的操作

排序策略與重疊判斷

絕大多數區間題的第一步是按起點排序O(n log n),整題的瓶頸通常就在這裡)。排序後相鄰兩區間 ab,若 a.end >= b.start 即重疊,可合併成 [a.start, max(a.end, b.end)]

fun merge(intervals: Array<IntArray>): Array<IntArray> {
    intervals.sortBy { it[0] }                 // 以起點排序,必要時起點相同再比終點
    val res = ArrayList<IntArray>()
    for (cur in intervals) {
        val last = res.lastOrNull()
        if (last != null && cur[0] <= last[1]) {
            last[1] = maxOf(last[1], cur[1])    // 重疊:延展終點
        } else {
            res.add(cur.clone())                // 不重疊:開新區間
        }
    }
    return res.toTypedArray()
}

IMPORTANT

先問清楚區間是[a, b],端點相觸算重疊)、還是半開[a, b),相觸不算重疊)。它直接決定重疊判斷該用 >= 還是 >,邊界題常因此出錯。

掃描線

當問題是「任一時刻最多同時有幾個區間」(會議室、航班、天際線)時,改用掃描線:把所有起點與終點拆成事件,按時間排序,起點 +1、終點 -1,掃描時維護當前重疊數的最大值。需要同時知道「誰最早結束」時,常再配一個最小堆追蹤進行中區間的終點。

跨倉庫導讀

#56Merge IntervalsMedium★★★★★⏱ O(n log n)#57Insert IntervalMedium★★★★★⏱ O(n)#252Meeting RoomsEasy★★★★★⏱ O(n log n)#253Meeting Rooms IIMedium★★★★★⏱ O(n log n)#352Data Stream as Disjoint IntervalsHard★★★★★⏱ O(log n)#435Non-overlapping IntervalsMedium★★★★★⏱ O(n log n)#1288Remove Covered IntervalsMedium★★★★★⏱ O(n log n)#1851Minimum Interval to Include Each QueryHard★★★★⏱ O((n + q) log n)