持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
合并区间
56. 合并区间 - 力扣(LeetCode)
以数组 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
解题思路
- 因为最终要执行合并动作,为了保证最终遍历的时间复杂度为O(n),需要先根据子区间的左边界排序
- 排序完成后,从左往后遍历子区间
- 如果结果集中最后一个interval小于当前遍历的interval,执行两个子区间的合并动作,并替换结果集中的最后一个interval
- 否则说明区间不连续,直接把当前的interval加在结果集中即可
代码实现
class Solution {
public int[][] merge(int[][] intervals) {
//排序:按子数组左区间排序
Arrays.sort(intervals, new Comparator<int[]>(){
public int compare(int[] interval1, int[] interval2) {
return interval1[0] - interval2[0];
}
});
List<int[]> result = new ArrayList<>();
//第一个interval先放进结果集中
result.add(intervals[0]);
//遍历即可
int[] current;
int[] prev;
for(int i = 1; i < intervals.length; i++){
current = intervals[i];
prev = result.get(result.size() - 1);
//前一个interval的右区间 > 当前interlval的左区间
if(prev[1] >= current[0]){
result.set(result.size() - 1,this.doMerge(prev,intervals[i]));
}else{
result.add(current);
}
}
return result.toArray(new int[result.size()][]);
}
private int[] doMerge(int[] prev, int[] current){
int left = prev[0];
int right = Math.max(prev[1],current[1]);
return new int[]{left,right};
}
}