[路飞]_程序员必刷力扣题: 56. 合并区间

132 阅读2分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战

56. 合并区间

以数组 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

排序+遍历比较相邻的交集情况

思路 这道题目是要让我们把有重叠的部分的数组进行合并,那么我们来看一下重叠的情况有几种

假设拥有两数组 [a,b] [c,d]

存在交集的可能如下:

  • a>=c&&a<=d a大于等于c并且a小于等于d
  • b>=c&&b<=d b大于等于c并且b小于等于d
  • c>=a&&c<=b c大于等于a并且c小于等于b
  • d>=a&&c<=b d大于等于a并且c小于等于b

那么不存在交集的情况呢?

  • a>d a大于d那么一定不存在交集
  • c>b c大于b也一定不存在交集

由上可得两个数组交集和不存在交集的所有情况,但是题目中的数组没有顺序,我们没办法保证相邻的不重叠,就不会与其他数组重叠,所以我们需要先排序,我们希望数组的0位按照从小到大的顺序进行排列,这里直接用sort完成排序

接下来,排序完毕后,我们得知,c必然大于等于a,所以只要c大于d那么一定不存在交集,否则存在交集

具体实现:

  • 先对数组进行排序,以每一项的[0]位为基准
  • 声明pre(上一个元素)为数组的第一个元素intervals[0]
  • 从1开始遍历数组,判断相邻两个数组是否存在交集
    • 如果不存在交集,则直接将pre放入结果res中
    • 如果存在交集则合并两个数组,取两数组0位的最小值和1位的最大值组成新的数组,保存在pre中
  • 循环完毕将pre中的最后一位放入res中 返回res即可
var merge = function (intervals) {
    var res = [];
    // 以item[0]为基准排序
    intervals.sort((a, b) => {
        return a[0] - b[0]
    })
    // pre 初始值
    var pre = intervals[0];
    for (var i = 1; i < intervals.length; i++) {
        var item = intervals[i];
        // [1,5] [2,6] 
        // 交集的情况 比较多
        // [a,b] [c,d]
        // a或者b  大于等于c并且小于等于d 
        // c或者d  大于等于a并且小于等于b 
        // 不交集的情况  就一种
        // [a,b] [c,d]
        // a>d 或者 c>b
        // 但是数组不是有序的啊   所以先排序
        if (item[0] > pre[1]) {
            res.push(pre);
            pre = item
        } else {
            pre[0] = Math.min(pre[0], item[0])
            pre[1] = Math.max(pre[1], item[1])
        }
    }
    if (pre) {
        res.push(pre)
    }
    return res
};