先看题目:
给出一个区间的集合,请合并所有重叠的区间。
示例 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] 可被视为重叠区间。
这里给出两种思路附加实现代码供参考:
- 思路一:先排序,再比较相邻的区间是否能够合并,时间复杂度为:2*n方(假设有n段区间)
- 思路二:直接比较相邻的区间是否能够合并,时间复杂度为:n方(假设有n段区间)
在解题之前,我们需要先弄清楚,任意两个区间之间存在哪些关系,也就是分类讨论的思想,图解如下:
清楚了上图描述的三种情况,我们就可以开始解题了:
解法一:
public int[][] merge(int[][] intervals) {
List<int[]> res = new ArrayList<>();
if (intervals == null || intervals.length == 0)
return res.toArray(new int[0][]);
// Arrays.sort(intervals, (a, b) -> a[0] - b[0]);// a[0] - b[0]大于0就交换顺序
// 根据二维数组第一个数字大小按每一行整体排序
Arrays.sort(intervals, new Comparator<int[]>() { //根据数组和迭代器指定按照哪种规则进行排序
@Override
public int compare(int[] o1, int[] o2) {
// TODO Auto-generated method stub
return o1[0] - o2[0]; //>0就交换顺序,说明是按照升序排序
}
});
int i = 0;
while (i < intervals.length) { //intervals.length = 行数
int left = intervals[i][0];
int right = intervals[i][1];
// i不能到最后一行,所以要小于(数组的长度 - 1)
// 判断所在行的right和下一行的left大小,对right重新进行赋最大值,之后再不断进行while循环判断
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讨论区,解释自己理解之后的思路:先排序,利用java集合的特性对所有区间进行排序,排序之后根据不同的情况是否合并区间,需要注意的是当出现需要合并的区间之后,下一次比较需要跳过一个区间,因为两个区间已经被合并成了一个,注意代码中的两处i++
。
时间复杂度为:O(2*n2) 空间复杂度:O(2n)
解法二:参考自leetcode提交区耗时为1ms的解法
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;
}
具体实现就是结合上面图解的三种情况来分析,在比较分析的时候需要添加额外的判断条件,判断条件虽然复杂了许多,但是将时间复杂度优化了到了解法一的一半。
时间复杂度:O(n2) 空间复杂度:O(n)