Description
給定一個區間的集合
intervals,求最少需要移除多少個區間才能讓剩下的區間互不重疊。
Example:
Input: intervals = [[1,2],[2,3],[3,4],[1,3]] Output: 1
Intuition#
等價問題:最多能保留多少個互不重疊的區間?用貪心策略每次選結束最早的區間。
- 這是經典的區間排程(Interval Scheduling)問題
- 按 end 排序,貪心地選結束最早的區間,可以留出最多空間給後面的區間
- 答案 = 總數 - 最多保留數
Approaches#
1: Sort by Start + Count Overlaps#
- 概念: 按起點排序,遇到重疊時移除 end 較大的那個(貪心保留 end 較小的)
- 時間複雜度:
O(n log n) - 空間複雜度:
O(1)— 不計排序空間
class Solution {
fun eraseOverlapIntervals(intervals: Array<IntArray>): Int {
intervals.sortBy { it[0] }
var count = 0
var prevEnd = intervals[0][1]
for (i in 1 until intervals.size) {
if (intervals[i][0] < prevEnd) {
count++
prevEnd = minOf(prevEnd, intervals[i][1])
} else {
prevEnd = intervals[i][1]
}
}
return count
}
}⭐2: Sort by End + Greedy Scheduling#
- 概念: 按終點排序,貪心選取不重疊的區間,最大化保留數量
- 時間複雜度:
O(n log n) - 空間複雜度:
O(1)— 不計排序空間
class Solution {
fun eraseOverlapIntervals(intervals: Array<IntArray>): Int {
intervals.sortBy { it[1] }
var kept = 1
var prevEnd = intervals[0][1]
for (i in 1 until intervals.size) {
if (intervals[i][0] >= prevEnd) {
kept++
prevEnd = intervals[i][1]
}
}
return intervals.size - kept
}
}🔑 Takeaways#
- Pattern: 區間排程 (Interval Scheduling) — 按 end 排序的貪心策略是最優的
- 關鍵技巧: 「最少移除」等價於「最多保留」;按結束時間排序能保證貪心的正確性(直覺:越早結束越好)