LeetCode 56「Merge Intervals」:給定區間集合,合併所有重疊區間。本文介紹排序 + 掃描線標準解法:按起點排序,線性掃描合併重疊區間。
start 升序(起點相同時按終點升序)。merged,遍歷排序後區間:merged 為空或當前區間 start > merged.back().end:無重疊,直接加入。merged.back().end = max(merged.back().end, cur.end)。| 情況 | 示例 | 合併結果 | 邏輯 |
|---|---|---|---|
| 部分重疊 | [1,3] [2,6] | [1,6] | end 取最大 |
| 包含關係 | [1,7] [2,4] | [1,7] | end 取最大(不變) |
| 無重疊 | [1,2] [3,4] | 分別保留 | 新增區間 |
class Solution {
public:
vector> merge(vector>& intervals) {
if (intervals.size() <= 1) return intervals;
sort(intervals.begin(), intervals.end(),
[](const vector& a, const vector& b) {
return a[0] < b[0] || (a[0] == b[0] && a[1] < b[1]);
});
vector> merged;
for (auto& iv : intervals) {
if (merged.empty() || iv[0] > merged.back()[1]) {
merged.push_back(iv);
} else {
merged.back()[1] = max(merged.back()[1], iv[1]);
}
}
return merged;
}
};
class Solution {
public int[][] merge(int[][] intervals) {
if (intervals.length <= 1) return intervals;
Arrays.sort(intervals, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
List merged = new ArrayList<>();
for (int[] iv : intervals) {
if (merged.isEmpty() || iv[0] > merged.get(merged.size()-1)[1]) {
merged.add(iv);
} else {
merged.get(merged.size()-1)[1] = Math.max(merged.get(merged.size()-1)[1], iv[1]);
}
}
return merged.toArray(new int[0][]);
}
}
iv[0] <= merged.back()[1] 即為重疊(含端點相接)。區間合併是「排序 + 貪心掃描」的經典模式。核心洞察:按起點排序後,重疊區間必然連續出現,只需與結果列表末尾比較即可。代碼極短,面試必會。掌握此模板,可秒殺所有區間合併/插入/交集/調度變體題。