小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
以数组 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 <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104
思路:
- 将单个索引用两个单元储存
- 区间的左边界存在索引的左边,右边界存储在索引的右边
- 因此,若有区间重合,那么重合点的左边会大于 1;
- 若区间相邻不重合,则在相邻点的右边会 = 0;
代码
/*
* @lc app=leetcode.cn id=56 lang=javascript
*
* [56] 合并区间
*/
// @lc code=start
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
var merge = function (intervals) {
// 差分数组
let axis = [];
intervals.forEach((interval) => {
let left = axis[2 * interval[0]] || 0;
let right = axis[2 * interval[1] + 1] || 0;
axis[2 * interval[0]] = left + 1;
axis[2 * interval[1] + 1] = right - 1;
});
let r = [];
let i = 0,
len = axis.length,
value = 0;
let left = -1;
while (i < len) {
value += axis[i] || 0;
// value > 0;
// 1、区间开始的标志
// 2、区间进行中
// value == 0
// 1、区间结束的标志
// 2、不再区间中
if (value > 0) {
if (left == -1) {
left = Math.floor(i / 2);
}
} else if (value == 0) {
if (left !== -1) {
r.push([left, Math.floor(i / 2)]);
left = -1;
}
}
i++;
}
return r;
};
// @lc code=end
思路2
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
var merge = function(intervals) {
// sort方法里面的比较函数 详情可以看看MDN a[0]-b[0]类似 a-b 升序 这并不奇怪
intervals.sort((a,b)=>a[0]-b[0])
// 注意这里对同一个数组进行了读写操作
// 存在i+1操作 所以intervals.length-1
for(let i=0;i<intervals.length-1;i++){
let start = intervals[i][1]
let end = intervals[i+1][0]
if(start>=end){
// 根据规律 说明这个区间可以合并
const data = [...intervals[i],...intervals[i+1]]
const item = [Math.min(...data), Math.max(...data)];
intervals.splice(i, 2, item);
i--; // 回退操作 看看新调整的区间可以跟后面的合并不
}
}
return intervals
};