题干
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
想法
最暴力的做法就是每一个数组都比较一下,但是这种想法过于愚蠢,相信聪明的你都完全不会考虑的。
我们可以假设,如果输入的数组是排好序的,就会变得很简单。
好,我们按照每个数组的第一个元素来进行排序:
这样前一个数组的第一个数一定小于后一个数组的第一个数
如果:
前一个数组的第二个数大于等于后一个数组的第一个数,那么这两个集合就有交集。
并集的左边界为前一个数组的第一个数,右边界为第一个数组的第二个数和第二个数组的大的那个。
直接讲我的代码,参考了https://blog.csdn.net/HaleyDong/article/details/90489902
他的讲解也很清楚,但是 它的代码是错的,错在了判断合并条件那一步。
官方解答
https://leetcode-cn.com/problems/merge-intervals/solution/he-bing-qu-jian-by-leetcode/
java代码
class Solution {
public int[][] merge(int[][] intervals) {
List <int[]> res=new ArrayList<>();
if(intervals==null){//判断空
return res.toArray(new int[0][]);
}
Arrays.sort(intervals,(a,b)->a[0]-b[0]);
int i=0;
int left=0;//左边界
int right=0;//右边界
while(i<intervals.length){
left=intervals[i][0];//为每个数组的第一个
right=intervals[i][1];//为每个数组的第二个
while(i<intervals.length-1&&right>=intervals[i+1][0]){//后一个的第一个必须小于之前的有边界
i++;
right=Math.max(right,intervals[i][1]);//右边界更新为两个数组第二个数中的大的
}
res.add(new int[]{left,right});//加到数组
i++;
}
return res.toArray(new int[0][]);
}
}
leetcode上最快的代码:思路差不多,数据结构更简练
class Solution {
public int[][] merge(int[][] intervals) {
if(intervals == null || intervals.length<=1){
return intervals;
}
int mergeCount = 0;
for(int i = 0;i<intervals.length;i++){
for(int j = i+1;j<intervals.length;j++){
if(intervals[i][1]>=intervals[j][0] && intervals[i][0]<=intervals[j][1]){
if(intervals[i][1]>intervals[j][1]){
intervals[j][1] = intervals[i][1];
}
if(intervals[i][0]<intervals[j][0]){
intervals[j][0] = intervals[i][0];
}
intervals[i] = null;
mergeCount++;
break;
}
}
}
int[][] result = new int[intervals.length-mergeCount][];
for(int i = 0,j = 0;j<intervals.length;j++){
if(intervals[j] != null){
result[i++] =intervals[j];
}
}
return result;
}
}
总结
这道题的官方解答是更新题目之前的,所以我这个应该是写的最全的