合并区间:左端点排序 + merged数组子项更新或者新添

123 阅读2分钟

思路

  • 按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的;可以避免讨论多种情况:比如比较[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;
        };