持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
题目描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 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] 可被视为重叠区间。
提示:
- 1 <= intervals.length <= 10^4
- intervals[i].length == 2
- 0 <= starti <= endi <= 10^4
题解
本题使用双指针的解法。使用左右指针,左指针指向区间的第一个数字即起始点,t 指向区间的右边界。右指针j不断向后移动,寻找可以合并的区间。当右指针指向区间的左边界小于 t ,说明这个区间连续且可以合并,那么把这个合并的区间加入到结果集合中,合并的区间的左边界是其实区间的左边界,右边界是右指针指向区间的右边界。然后跳过已经合并的区间继续寻找。
注意:
在做本题的时候,应该先对数组进行排序,因为我们的合并判断条件是后面区间的第一个数小于第一个区间的第二个数。
代码
class Solution {
public int[][] merge(int[][] intervals) {
// 先排序
List<int[]> inter = Arrays.asList(intervals);
List<int[]> newInter = new ArrayList<>(inter);
newInter.sort((o1, o2) -> o1[0] - o2[0]);
// 使用左右指针
List<int[]> list = new ArrayList<>();
int j = 0;
for(int i = 0;i < intervals.length;){
int t = newInter.get(i)[1];
j = j + 1;
// 前一区间的结尾大于新区间的开头
while(j < intervals.length && t >= newInter.get(j)[0]){
t = Math.max(newInter.get(j)[1], t);
j ++;
}
list.add(new int[]{newInter.get(i)[0], t});
// 跳过已经合并的区间集合
i = j;
}
int[][] res = new int[list.size()][2];
int i = 0;
for(int[] ans : list){
res[i][0] = ans[0];
res[i][1] = ans[1];
i ++;
}
return res;
}
}