1.题目描述:
以数组intervals表示若干个区间的集合,其中单个区间为intervals[i] = [starti, endi]。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
2.贪心算法:
思路类似leetcode435. 无重叠区间和leetcode452. 用最少数量的箭引爆气球。区别是需要维护一个存放结果的集合,并且一旦发现不重叠区间则直接放入结果集中,在下个循环来动态对放入结果集的区间右端点进行扩大(否则把正确合并完的区间放入结果集中较为困难)。按照区间起点升序代码如下,使用区间右节点升序排列无法套用,可能在很后面会出现某一个区间起点较小的情况。
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] a, int[] b) {
return a[0] - b[0];
}
});
List<int[]> list = new ArrayList<>();
list.add(intervals[0]);
int max = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] <= max) {
max = Math.max(max, intervals[i][1]);
list.get(list.size() - 1)[1] = max;//扩容区间
} else {
list.add(intervals[i]);
max = intervals[i][1];//更新max
}
}
return list.toArray(new int[list.size()][]);
}
}
又想了一下,按照区间终点升序,遍历从右侧开始即可:
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] a, int[] b) {
return a[1] - b[1];
}
});
List<int[]> list = new ArrayList<>();
list.add(intervals[intervals.length - 1]);
int min = intervals[intervals.length - 1][0];
for (int i = intervals.length - 2; i >= 0; i--) {
if (intervals[i][1] >= min) {
min = Math.min(min, intervals[i][0]);
list.get(list.size() - 1)[0] = min;
} else {
list.add(intervals[i]);
min = intervals[i][0];
}
}
return list.toArray(new int[list.size()][]);
}
}