题目
以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
题解
class Solution {
public int[][] merge(int[][] intervals) {
if (intervals.length == 0) {
// 如果输入的区间集合为空,直接返回一个空的二维数组。
return new int[0][2];
}
// 对输入的区间集合按照区间的起始位置进行排序。
Arrays.sort(intervals, new Comparator<int[]>() {
public int compare(int[] interval1, int[] interval2) {
return interval1[0] - interval2[0];
}
});
// 创建一个ArrayList用于存储合并后的区间。
List<int[]> merged = new ArrayList<int[]>();
// 遍历排序后的区间集合,对于每一个区间,如果当前合并后的区间集合为空或者当前区间的起始位置大于已合并区间集合中最后一个区间的结束位置,则直接将当前区间添加到合并后的区间集合中;否则,更新已合并区间集合中最后一个区间的结束位置为当前区间的结束位置与已合并区间集合中最后一个区间的结束位置的最大值。
for (int i = 0; i < intervals.length; ++i) {
int L = intervals[i][0], R = intervals[i][1];
if (merged.size() == 0 || merged.get(merged.size() - 1)[1] < L) {
merged.add(new int[] { L, R });
} else {
merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], R);
}
}
// 将ArrayList转换为一个二维数组并返回。
return merged.toArray(new int[merged.size()][]);
}
}
分析
原理及其正确性:
原理:如果我们按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的。
正确性(反证法):试想,区间按左端点排序后,有两个不相邻的区间(假设第 k 和 第 k+2 个区间)可合并,则一定有第 k 个区间的右端点大于或等于第 k+2 个区间的左端点,而 第 k+1 个区间的左端点是一定小于或等于第 k+2 个区间的左端点的,则一定有:第 k 个区间的左端点大于或等于第 k+1 个区间的左端点,那么第 k 个区间与第 k+1 个区间一定是能合并的,k 与 k+y 中间的若干区间与第 k 个区间都是能合并的。所以不存在间隔但可合并的区间。