【leetCode】 - 合并区间

133 阅读2分钟

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

题目

leetcode-cn.com/problems/me…

解法

我们希望一次性遍历目标数组就完成,这当然是最好的了,但考虑以下问题:

  • 一旦发生了目标和结果中的合并,那么:

    • 我们如何要对结果里的数据进行处理?
    • 如果再次发生合并,是否我们还要再次进行相同的操作,直到本次没有再可以合并的了?

因此,我们将数据先按照第一个数(也就是左区间点)进行排序,这样子有几个好处:

  • 因为排序过了,在进行比较的过程中就可以省略左区间的相互比较,取出来的目标数据的左区间,一定不小于结果的左区间。

  • 也因为上面的关系,我们每次涉及到的结果数组,只需要考虑当前最后一个就可以了。因为:

    • 我们的目标数组,要么和数组的最后一个相交(目标左<=结果右,此时合并进去。而且因为排序,我们只要进行这一次右端点的交换就可以了),要么就超过了数组最后一个区间的范围(目标左>结果右,此时我们在结果集里的最后面加一个)。
 //我们希望在数轴上按照从前往后的顺序来排列,这样我们就不需要考虑合并的问题了
 public static int[][] merge(int[][] intervals) {
     if(intervals.length == 0) return new int[0][0];
     //先排序
     Arrays.sort(intervals, Comparator.comparingInt(o -> o[0]));
     int[][] res = new int[intervals.length][];
     res[0] = intervals[0];
     int idx = 0;
     for (int i = 1; i < intervals.length; i++) {
         int l = intervals[i][0], r = intervals[i][1];
         //因为排序过了,因此可以保证后面取出来的左边界数不小于前面的.我们只需要做两件事:
         //1.输入区间,是否可以和当前区间合并?不可以的话,就添加到后面
         //2.当前区间,是否可以扩展指定区间?
         if(l>res[idx][1]){
             idx++;
             res[idx] = intervals[i];
         }else{
             res[idx][1] = Math.max(res[idx][1],r);
         }
     }
     return Arrays.copyOf(res,idx+1);
 }

执行用时:7 ms, 在所有 Java 提交中击败了63.91%的用户

内存消耗:40.8 MB, 在所有 Java 提交中击败了82.94%的用户

我们分析一下我们的时间复杂度:

  • 排序O(NlogN)
  • 循环处理O(N)

也就是说,我们的解法的时间复杂度实际上是由排序决定的。

\