56. Merge Intervals
MediumDescription
給定一個區間的集合
intervals,合併所有重疊的區間,回傳不重疊的區間陣列。
Example:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]]
Intuition#
按起點排序後,相鄰區間若重疊就合併,不重疊就開始新區間。
- 排序是關鍵的第一步,排序後只需比較相鄰區間
- 重疊判斷:前一個區間的 end >= 下一個區間的 start
- 合併:更新 end 為兩者的 max
Approaches#
1: Sort and Compare Adjacent#
- 概念: 排序後遍歷,逐一與結果中最後一個區間比較,決定合併或新增
- 時間複雜度:
O(n log n)— 排序主導 - 空間複雜度:
O(n)— 輸出空間
class Solution {
fun merge(intervals: Array<IntArray>): Array<IntArray> {
intervals.sortBy { it[0] }
val result = mutableListOf<IntArray>()
for (interval in intervals) {
if (result.isEmpty() || result.last()[1] < interval[0]) {
result.add(interval)
} else {
result.last()[1] = maxOf(result.last()[1], interval[1])
}
}
return result.toTypedArray()
}
}⭐2: Sort and Merge (Cleaner Variable Tracking)#
- 概念: 用變數追蹤當前合併中的區間邊界,邏輯更清晰
- 時間複雜度:
O(n log n) - 空間複雜度:
O(n)— 輸出空間
class Solution {
fun merge(intervals: Array<IntArray>): Array<IntArray> {
if (intervals.isEmpty()) return emptyArray()
intervals.sortBy { it[0] }
val result = mutableListOf<IntArray>()
var start = intervals[0][0]
var end = intervals[0][1]
for (i in 1 until intervals.size) {
if (intervals[i][0] <= end) {
end = maxOf(end, intervals[i][1])
} else {
result.add(intArrayOf(start, end))
start = intervals[i][0]
end = intervals[i][1]
}
}
result.add(intArrayOf(start, end))
return result.toTypedArray()
}
}🔑 Takeaways#
- Pattern: 排序 + 線性掃描 — 區間問題的經典套路
- 關鍵技巧: 排序後只需和前一個區間比較;合併操作就是更新 end 為 max