力扣第五十六题-合并区间

531 阅读2分钟

这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战

前言

力扣第五十六题 合并区间 如下所示:

以数组 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] 可被视为重叠区间。

一、思路

合并区间 这一题中对 重叠区间 的定义为: 如果有 startj >= endi 则表示 ij 两个区间有重叠,如 [2, 5][3, 6] 会有重叠部分。

题目中的 区间集合 不一定是按从左到右依次排列的,这对于合并重叠的区间会十分的困难。

所以我们第一步就是将 区间集合 按照 左边界升序排列,例如 [[5, 6], [1, 3], [2, 4]] 按照左边界升序后就变为了 [[1, 3], [2, 4], [5, 6]]

对于每个区间来说,它有可能是左边界重叠或右边界重叠。如果不将区间排序的话,就需要对每一个区间的左右边界判断是否重叠,还要判断是否会与新合并后的区间重合,这会大大增加算法的时间复杂度。

第二步就比较容易了,只需要遍历所有的区间,并判断相邻的两个区间是否重叠,如果重叠就合并,如 [[1, 3], [2, 4]] 这两个区间有重叠,则合并为 [1, 4]

综上所述,实现的思路总共分为两步:

  1. 左边界升序排列
  2. 遍历并合并相邻的重叠区间

举个例子

此处以示例1中的 intervals = [[1,3],[2,6],[8,10],[15,18]] 作为例子

int[] pre:表示相邻的前一个区间

  1. i=0 时,pre = [1, 3]
  2. i=1 时,发现 pre[1] > intervals[1][0],即 3 > 2,此时合并两个区间 pre = [1, 6]
  3. i=2 时,发现 pre[1] < intervals[1][0],即 6 < 8,说明不会重叠,记录结果 [1, 6],并更新 pre 为当前区间 pre = [8, 10]
  4. i=3 时,发现 pre[1] < intervals[1][0],即 10 < 15,说明不会重叠,记录结果 [8, 10],并更新 pre 为当前区间 pre = [15, 18]
  5. 遍历结束,返回存储的结果集即可

二、实现

实现代码

实现代码与思路中基本保持一致,略有改动的地方就是会在遍历结束后记录最后一个区间

    public int[][] merge(int[][] intervals) {
        int[][] ret = new int[intervals.length][];
        // 间隔数组按照左端升序(冒泡)
        Arrays.sort(intervals, Comparator.comparingInt(v -> v[0]));
        int[] pre = intervals[0];
        int index = 0;
        for (int i=1; i<intervals.length; i++) {
            if (intervals[i][0] > pre[1]){    // 如果当前区间的左边界大于前者的右边界则为不重叠
                ret[index] = pre;   // 保存结果
                index++;
                pre = intervals[i];
            } else if (intervals[i][1] > pre[1]) {  // 重叠且右边界溢出
                pre[1] = intervals[i][1];
            }
        }
        ret[index] = pre;   // 保存最后一个分组
        return Arrays.copyOf(ret, index + 1);
    }

测试代码

    public static void main(String[] args) {
        int[][] nums = {{1,3},{2,6},{8,10},{15,18}};
        int[][] nums1 = {{1,3}};
        new Number56().merge(nums);
    }

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥