题目描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
解题思路
给定一组区间,需要将所有重叠的区间合并,并返回合并后的区间集合。
- 排序:
- 首先按照每个区间的起始值升序排序,这样可以保证后续遍历时能够轻松判断区间是否重叠。
- 合并逻辑:
- 使用一个临时区间
term
存储当前正在合并的区间。 - 遍历每个区间,如果当前区间和
term
有重叠(即term[1] >= intervals[i][0]
),更新term
的结束位置为两个区间结束位置的较大值。 - 如果没有重叠,则将
term
加入结果集合,并用当前区间更新term
。
- 使用一个临时区间
- 返回结果:
- 遍历结束后,需将最后一个
term
加入结果集合,最终返回结果。
- 遍历结束后,需将最后一个
源码实现
class Solution {
public int[][] merge(int[][] intervals) {
// 边界条件:如果输入数组为空,直接返回空数组
if (intervals.length == 0) return intervals;
// 1. 对二维数组按起始值(第一列)升序排序
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
// 2. 创建结果列表用于存储合并后的区间
List<int[]> list = new ArrayList<>();
// 初始化一个临时区间,先取排序后的第一个区间
int[] term = intervals[0];
// 3. 遍历剩余区间,判断是否需要合并
for (int i = 1; i < intervals.length; i++) {
if (term[1] >= intervals[i][0]) {
// 如果当前区间和临时区间有重叠,更新临时区间的结束位置
term[1] = Math.max(term[1], intervals[i][1]);
} else {
// 如果当前区间与临时区间无重叠,将临时区间加入结果集
list.add(term);
// 更新临时区间为当前区间
term = intervals[i];
}
}
// 最后一个临时区间加入结果集
list.add(term);
// 4. 将结果列表转换为二维数组返回
return list.toArray(new int[list.size()][2]);
}
}
复杂度分析
-
时间复杂度:
- 排序部分: 使用
Arrays.sort()
对二维数组排序,时间复杂度为 O(nlogn)O(nlogn),其中 nn 为区间的个数。 - 遍历部分: 遍历所有区间进行合并操作,时间复杂度为 O(n)O(n)。
- 总体时间复杂度: O(nlogn)O(nlogn)。
- 排序部分: 使用
-
空间复杂度:
- 结果集: 使用
ArrayList
存储合并结果,空间复杂度为 O(n)O(n),其中 nn 为区间的个数。 - 排序的辅助空间: 内部排序实现通常为原地排序,额外空间复杂度为 O(1)O(1)。
- 总体空间复杂度: O(n)O(n)。
- 结果集: 使用