题目描述
解题思路
本题的思路就是按照左边界排序,根据重复区间进行合并,每次合并后区间有边界取最大的右边界。
那么我按照左边界排序,排序之后局部最优:每次合并都取最大的右边界,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。
按照左边界从小到大排序之后,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]左边界 < intervals[i - 1]右边界,则一定有重复,因为intervals[i]的左边界一定是大于等于intervals[i - 1]的左边界。
即:intervals[i]的左边界在intervals[i - 1]左边界和右边界的范围内,那么一定有重复!
这么说有点抽象,看图:(注意图中区间都是按照左边界排序之后了)
知道如何判断重复之后,剩下的就是合并了,如何去模拟合并区间呢?
其实就是用合并区间后左边界和右边界,作为一个新的区间,加入到result数组里就可以了。如果没有合并就把原区间加入到result数组。
public int[][] merge(int[][] intervals) {
List<int[]> res = new ArrayList<>();
if (intervals.length == 0) return (int[][]) res.toArray();
Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0])); // 根据左区间进行排序
int start = intervals[0][0];
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] > intervals[i - 1][1]) {
res.add(new int[]{start, intervals[i - 1][1]}); // 不能合并,加入结果集
start = intervals[i][0]; // 更新开始区间
} else {
// 此时可以合并,则将右区间更新,此时不用加入结果集,下一次循环会判断这次区间
intervals[i][1] = Math.max(intervals[i - 1][1], intervals[i][1]);
}
}
res.add(new int[]{start, intervals[intervals.length - 1][1]});// 加入最后一个区间
return res.toArray(new int[res.size()][2]);
}