题目描述
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例:
输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
提示:
1 <= intervals.length <= 104intervals[i].length == 20 <= starti <= endi <= 104
题解
贪心算法
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
var merge = function(intervals) {
intervals.sort((a,b)=>a[0]-b[0]);
let pre = intervals[0];
let result = [];
for(let i = 0;i<intervals.length;i++){
let cur = intervals[i];
if(cur[0]>pre[1]){
result.push(pre);
pre = cur;
}else{
pre[1] = Math.max(cur[1],pre[1])
}
}
result.push(pre);
return result;
};
分析题目,解决思路是:找出重叠区间-合并重叠区间-返回结果
代码首先通过sort()方法先对数组进行排序,依据是按照内部的左边界从小到大排序。以便后续进行重叠的判断
排序完成后,采用贪心策略进行单次遍历合并:
pre: 存储当前正在构建、合并的区间(即上一个被合并后的结果)。初始化为排序后的第一个区间intervals[0]。result: 存储最终不重叠的区间集合。
遍历逻辑: 从第二个区间开始遍历,将当前区间 cur 与正在构建的 pre 区间进行比较。
if(cur[0] > pre[1]):当前区间的起点 大于上一个合并区间的终点 。说明cur和pre没有重叠
- 将已经完成合并的
pre区间加入结果列表result.push(pre)。 - 将当前区间
cur作为新的、待合并的区间起点:pre = cur。
else(即 ):当前区间的起点 小于或等于上一个合并区间的终点 。即两个区间有重叠
- 这两个区间可以合并。
- 合并后的新终点应该是两者终点中较大的那个:
pre[1] = Math.max(cur[1], pre[1])。 - 保持
pre不变,继续等待下一个区间。
结果处理
- 循环结束后: 循环结束后,最后一个正在构建的
pre区间还未被加入result列表。执行result.push(pre),以确保将最后一个合并完成的区间添加到结果中。
时间,空间复杂度
时间复杂度 O(N \log N)
排序操作是主要的时间开销,复杂度为 。
空间复杂度:O(\log N) 或 O(N)
排序所需空间: 到 (取决于 JavaScript 引擎使用的排序算法)。
结果所需空间: ,最坏情况下(所有区间都不重叠)result 数组会存储 个区间。
综合空间复杂度为 。