思路
- 按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的;可以避免讨论多种情况:比如比较[a,b],[c,d],会出现针对a<c<b<d,a<c<d<b以及c<a<b<d,c<a<d<b等多种情况,因为排序之后,c肯定是大于等于a的,然后b肯定是大于a的,如果按照区间的左端点排序,那么在排完序的列表中,那么我们就可以只讨论一种情况,如果c小于等于b,我们直接取b和d的最大值,重新赋值给b,然后继续往后遍历[e,f],[g,h]…等等
- 另外,在上一段落中提到,如果c小于等于b,我们直接取b和d的最大值,重新赋值给b,这里的意思就是直接修改merged数组本身(这是题目要求会返回的数组)的子项,由于intervals数组已经按照区间的左端点排序过,所以根据intervals数组衍生出来的merge数组的子项的左端点也是存在从小到大的顺序的,所以每次遍历排序后的intervals数组的时候,可以直接通过将merged数组的最后一项的左端点,比如[a,b]中的a与当前intevals数组正在遍历的子项,[c,d]进行比较,如果c≤a,那么将b = Math.max(b,d),以此类推。
题目
以数组 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:错误事例
考虑不全,需要排序
/**
* @param {number[][]} intervals
* @return {number[][]}
*/var merge = function (intervals) {
let n = intervals.length;
let map = new Array(1).fill([]);
map[0] = [intervals[0][0], intervals[0][1]]
for (let i = 1; i < n; i++) {
let mergeItemIndex = map.findIndex((item) => {
return intervals[i][0] <= item[1] && intervals[i][1] > item[1]
})
if (mergeItemIndex !== -1) {
map[mergeItemIndex] = [map[mergeItemIndex][0], intervals[i][1]]
} else {
map.push([intervals[i][0], intervals[i][1]])
}
}
return map;
};
代码2:官方解法
/**
* @param {number[][]} intervals
* @return {number[][]}
*/var merge = function (intervals) {
// 按照区间的左端点排序, 那么在排完序的列表中,可以合并的区间一定是连续的
intervals.sort((a,b)=>{
return a[0] - b[0]
})
// 初始化数组,存储最终的答案
let mergedArr = new Array(1).fill([]);
mergedArr[0] = [intervals[0][0],intervals[0][1]]
let n = intervals.length;
// 遍历排序后的intervals数组
for(let i = 1;i < n; i++) {
let len = mergedArr.length;
if(intervals[i][0] <= mergedArr[len - 1][1]) {
mergedArr[len - 1][1] = Math.max(mergedArr[len - 1][1],intervals[i][1])
} else {
mergedArr.push([intervals[i][0],intervals[i][1]])
}
}
return mergedArr;
};