问题描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
例如:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
先给大家贴上我自己的代码
我的想法是先将所有的数据按照区间开始由小到大排序,自己根据归并排序的思路写了一个区间的排序
/**
* 根据归并排序的思想进行排序,将待排序数组拆分后,对比合并成新的数组
*/
public static int[][] arraySort(int[][] intervals){
if (intervals.length==1){
return intervals;
}
int mid = intervals.length >> 1;
int[][] left = Arrays.copyOfRange(intervals,0,mid);
int[][] right = Arrays.copyOfRange(intervals,mid,intervals.length);
return combineArray(arraySort(left),arraySort(right));
}
/**
* 数组合并,成新的有序数组
*/
public static int[][] combineArray(int[][] leftArray,int[][] rightArray){
int[][] result = new int[leftArray.length+rightArray.length][2];
int leftIndex = 0;
int rightIndex = 0;
for (int i = 0 ; i< result.length;i++){
if (leftIndex>= leftArray.length){
// 左侧的数据已经遍历完毕
result[i] = rightArray[rightIndex++];
} else if(rightIndex>= rightArray.length){
// 右侧数据已经遍历完毕
result[i] = leftArray[leftIndex++];
} else if(leftArray[leftIndex][0]<rightArray[rightIndex][0]){
// 左侧的范围小
result[i] = leftArray[leftIndex++];
} else if(leftArray[leftIndex][0]>=rightArray[rightIndex][0]){
// 右侧的范围小
result[i] = rightArray[rightIndex++];
}
}
return result;
}
public int[][] merge(int[][] intervals) {
// 调用自己的排序算法
intervals = arraySort(intervals);
// 创建新的列表,存储排序区间
List<int[]> list = new ArrayList<>();
// 循环时候,默认区间为第一个区间
for (int i = 0 ;i < intervals.length;){
int[] result = new int[2];
int[] temp1 = intervals[i];
// 由于排序后的区间是有序的,所以开始第一个区间的开始就是合并区间的开始
result[0] = temp1[0];
int end = temp1[1];
while (i < intervals.length - 1) {
// 向后延申寻找,直到没有重合的区间
int[] temp2 = intervals[i + 1];
if(end >= temp2[0]) {
// 寻找合并区间的结束区间
end = Math.max(end,temp2[1]);
// 同时for循环向后移动,不会再次对比已经合并的数据
i++;
} else {
break;
}
}
// 循环结束,意味这本轮元素区间合并完成
result[1] = end;
list.add(result);
// 由于每次对比都是将后一个与i进行对比,因此,如果后一个不在区间内的同时,for循环
// 元素后移,到下一个元素
i++;
}
// 返回结果
return list.toArray(new int[list.size()][2]);
}
运行结果不尽如人意
找了一个案例参考了一下最后发现,排序部分消耗了大量的时间
public int[][] merge(int[][] intervals) {
if(intervals == null || intervals.length<=1)
return intervals;
// 排序部分修改为Arrays.sort()方法,果然提升了不少
// 革命尚未成功,同志仍需努力啊
Arrays.sort(intervals,new Comparator<int[]>(){
@Override
public int compare(int[] a,int[] b){
return a[0]-b[0];
}
});
List<int[]> list = new ArrayList<>();
for (int i = 0 ;i < intervals.length;){
int[] result = new int[2];
int[] temp1 = intervals[i];
result[0] = temp1[0];
int end = temp1[1];
while (i < intervals.length - 1) {
int[] temp2 = intervals[i + 1];
if(end >= temp2[0]) {
end = Math.max(end,temp2[1]);
i++;
} else {
break;
}
}
i++;
result[1] = end;
list.add(result);
}
return list.toArray(new int[list.size()][2]);
}