56. 合并区间
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:
输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
注意:输入类型已于2019年4月15日更改。 请重置默认代码定义以获取新方法签名。
提示:
intervals[i][0] <= intervals[i][1]
思路:排序 + 双指针
先将二维数组中的所有子区间按左边界从小到大排序。
然后遍历所有的子区间,维护两个数字,分别是当前合并区间的左边界和右边界,每次遍历时,判断当前合并的右边界是否小于下个小区间的左边界,如果小于的话,说明当前合并区间和下个小区间没有交集,将当前的左右边界作为一个区间的左右边界存入结果集中,并重置下个合并区间的左右边界为下个小区间的左右边界;如果当前合并区间的右边界大于等于下个小区间的左边界,说明当前合并区间和下个小区间有交集,把合并区间的右边界更新为 下个小区间的右边界和当前合并区间右边界中的较大值,从而让合并区间扩张。
最后还需要再将合并区间的左右边界添加到结果集中一次,因为循环中没有把最后一个合并区间添加到结果集中。
1 class Solution {
2 public int[][] merge(int[][] intervals) {
3 if(intervals == null || intervals.length == 0){
4 return new int[0][0];
5 }
6 // 将所有的区间按左区间大小从小到大排序
7 Arrays.sort(intervals, new Comparator<int[]>(){
8 public int compare(int[] a, int[] b){
9 return a[0] - b[0];
10 }
11 });
12 int leftBorder = intervals[0][0], rightBorder = intervals[0][1];
13 int len = intervals.length;
14 ArrayList<int[]> res = new ArrayList<>();
15 for(int i = 1; i < len; i++){
16 if(rightBorder < intervals[i][0]){ // 说明不可能和下个集合有交集
17 //System.out.println(leftBorder + " " + rightBorder);
18 res.add(new int[]{leftBorder, rightBorder});
19 leftBorder = intervals[i][0];
20 rightBorder = intervals[i][1];
21 }else{
22 rightBorder = Math.max(rightBorder, intervals[i][1]); // 说明有交集
23 }
24 }
25 res.add(new int[]{leftBorder, rightBorder});
26 return res.toArray(new int[res.size()][2]);
27 }
28 }
leetcode 执行用时:7 ms > 90.82%, 内存消耗:41 MB > 92.54%
复杂度分析:
时间复杂度:O(nlogn), n 为数组长度,时间花费主要分为两部分,一部分是排序,时间复杂度为O(nlogn), 接下来一次遍历的时间花费为O(n)。
空间复杂度:O(1), 如果不算上 res 这个结果列表的空间开销的话,那空间复杂度就是O(1)