LeetCode 56. 合并区间
题目描述
✅ 56. 合并区间

题意分析
输入若干个闭区间,需要把互相重叠的部分合并,返回一组互不重叠的区间。合并前后覆盖的所有位置必须相同,不能遗漏原区间,也不能把中间未被覆盖的空隙补进去。
闭区间包含两端,因此一个区间的右端点等于另一个区间的左端点时,也需要合并。区间还可能重复、相互包含或通过其他区间连接成一整段,输入顺序不保证有序。
解法:排序 + 贪心合并
核心思路
[!blue]
如果按原顺序处理,当前区间可能与结果中的任意一段重叠,难以只比较一次就确定位置。先按左端点升序排序,就能保证后来的区间不会从更靠左的位置开始。
扫描时维护结果
merged,其中的区间始终按位置排列且互不重叠。只需检查最后一段last:更早各段的右端点都小于last的左端点,而当前区间的左端点不小于last的左端点,因此不可能再与更早各段相交。若
last.end < current.start,两段之间有空隙。后续区间的起点只会更大,也无法填补这个空隙,所以last已经确定,可以把当前区间作为新的一段追加。否则两段重叠或共享端点,应合成一段。左端点仍取
last.start,右端点取两者的最大值。取最大值既能扩大覆盖范围,也能让被包含的区间不缩短原来的范围。每次合并后继续与新的最后一段比较,连锁重叠便会自然合成一个区间。
解题步骤
- 按左端点升序排列所有区间,创建空结果列表
merged。- 依次取出当前区间。若结果为空,直接放入结果。
- 若最后一段的右端点严格小于当前左端点,说明存在间隔,追加当前区间。
- 否则将最后一段的右端点更新为两个右端点的较大值,不新增区间。
- 返回结果。代码会原地排序,并复用输入中的区间数组或切片,因此合并时也可能修改输入区间的右端点。
代码实现
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (first, second) -> Integer.compare(first[0], second[0]));
List<int[]> merged = new ArrayList<>();
for (int[] interval : intervals) {
// 闭区间端点相等仍重叠,严格分离时才新开一段。
if (merged.isEmpty() || merged.get(merged.size() - 1)[1] < interval[0]) {
merged.add(interval);
continue;
}
int[] last = merged.get(merged.size() - 1);
// 只扩大最后一段的右端;这里修改的是复用的原区间数组。
last[1] = Math.max(last[1], interval[1]);
}
return merged.toArray(new int[merged.size()][]);
}
}
import "sort"
func merge(intervals [][]int) [][]int {
sort.Slice(intervals, func(i int, j int) bool {
return intervals[i][0] < intervals[j][0]
})
merged := make([][]int, 0, len(intervals))
for _, interval := range intervals {
// 闭区间端点相等仍重叠,严格分离时才新开一段。
if len(merged) == 0 || merged[len(merged)-1][1] < interval[0] {
merged = append(merged, interval)
continue
}
last := merged[len(merged)-1]
// 只扩大最后一段的右端;这里修改的是复用的原区间切片。
if interval[1] > last[1] {
last[1] = interval[1]
}
}
return merged
}
复杂度分析
设输入有
n个区间。
- 时间复杂度:$O(n \log n)$,排序需要 $O(n \log n)$,合并扫描只需 $O(n)$。
- 空间复杂度:$O(n)$,结果最多保存
n段。不计结果存储时,Java 对对象数组排序还需要 $O(n)$ 辅助空间,Go 排序使用 $O(\log n)$ 调用栈。
关键点总结
[!green]
- 按左端点排序后,只需要检查最后一段;更早各段已经与当前及后续区间隔开。
- 出现严格空隙才新建一段,共享端点仍属于同一段。
- 合并是在保持左端点的同时扩大右端点,遇到包含关系时范围保持不变。
易错点总结
[!yellow]
- 忘记排序就只比较结果末尾,可能漏掉与更早结果的重叠。
- 直接用当前右端点覆盖末尾右端点,会在当前区间被包含时错误地缩小范围。
- 把端点相等判断为不重叠,会漏掉闭区间共享的端点。
- 排序只需要比较起点;起点相同时,无论哪个区间先出现,右端点取最大值都能正确合并。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 57. 插入区间 | 中等 | 同样维护互相重叠的区间,原题输入已有序且不重叠,只需插入一个新区间后合并。 |
| 435. 无重叠区间 | 中等 | 同样按区间关系处理重叠,原题删除最少区间保持不相交,本题把重叠部分合成并集。 |
| 986. 区间列表的交集 | 中等 | 按起点排序后合并重叠区间;本题输出区间并集,该题以双指针枚举两个区间表的交集。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!