题目:
Given a collection of intervals, merge all overlapping intervals.
Example 1:
Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
Example 2:
Input: [[1,4],[4,5]]
Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.
NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature.
解答:
本题参考了很多他人的答案,值得学习。
解题思路如下:
- 将给定的集合,根据每个区间的起始点,按照从大到小的顺序进行排序。其中通过采用匿名内部类,重写了 Comparator 接口中的 compare 方法,对数组进行了自定义排序
- 遍历排序后的集合进行合并,若位置 i 的右区间 > 位置 i+1 的左区间,则说明有重合需要合并,取右区间值 = Math.max(end, intervals[i+1][1])。不能合并的则直接 add
- 将最终结果的 ArrayList 通过 toArray() 方法转换为二维数组形式并返回
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] a1, int[] a2) {
return a1[0]-a2[0];
}
});
List<int []> res = new ArrayList<>();
for(int i=0; i<intervals.length; i++) {
int start = intervals[i][0];
int end = intervals[i][1];
while(i<intervals.length-1 && end>=intervals[i+1][0]) {
end = Math.max(end, intervals[i+1][1]);
i++;
}
res.add(new int[] {start, end});
}
return res.toArray(new int[res.size()][2]);
}
}
补充:
Arrays.sort() 方法
本题中通过采用匿名内部类重写 Comparator 接口中的 compare 方法,对数组进行了自定义的排序。分析 Arrays.sort() 源码可以看到:
* @param <T> the class of the objects to be sorted
* @param a the array to be sorted
* @param c the comparator to determine the order of the array. A
* {@code null} value indicates that the elements'
* {@linkplain Comparable natural ordering} should be used.
* @throws ClassCastException if the array contains elements that are
* not <i>mutually comparable</i> using the specified comparator
* @throws IllegalArgumentException (optional) if the comparator is
* found to violate the {@link Comparator} contract
*/
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
// Android-changed: LegacyMergeSort is no longer supported
// if (LegacyMergeSort.userRequested)
// legacyMergeSort(a, c);
// else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
通常,Arrays.sort(T[] a, Comparator<? Super T> c)
用 Comparator 接口可以实现自定义排序规则。比如实现降序排列:
import java.util.*;
public class Main {
public static void main(String[] args){
Integer[] arr = {5,4,7,9,2,12,54,21,1};
//降序
Arrays.sort(arr, new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return b-a;
}
});
System.out.println(Arrays.toString(arr)); //[54, 21, 12, 9, 7, 5, 4, 2, 1]
}
}
这里有一篇博文,介绍了 Arrays.sort() 方法:深入理解Arrays.sort() ,其中我们也可以学习到,Arrays.sort() 的源码实现为两枢轴快速排序
这里附一个匿名内部类的简要讲解:匿名内部类
ArrayList 转换为数组
ArrayList 可采用 toArray() 方法将List转为数组。toArray() 有两个重载形式:
list.toArray();
:将 list 直接转为 Object[] 数组list.toArray(T[] a);
:将 list 转化为所需要类型的数组,即会转化为与 list 内容相同的类型
如果需要类型转换,不能采用将list 直接强制类型转换,如错误写法:
ArrayList<String> list=new ArrayList<String>();
for (int i = 0; i < 4; i++) {
list.add(""+i);
}
String[] array= (String[]) list.toArray(); //报错
注意:不能将Object[] 转化为String[]。java中的强制类型转换只能针对单个对象,不能将数组整个强制类型转换,需要单个元素遍历并转换类型
Object[] arr = list.toArray();
for (int i = 0; i < arr.length; i++) {
String e = (String) arr[i];
System.out.println(e);
}
这样的过程显得过于繁琐。所以我们通常采用list.toArray(T[] a);
进行集合转为数组的操作
String[] array =new String[list.size()];
list.toArray(array);