力扣第五十七题-插入区间

234 阅读3分钟

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

前言

力扣第五十七题 插入区间 如下所示:

给你一个 无重叠的,按照区间起始端点排序的区间列表。

在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。  

示例 1:

输入: intervals = [[1,3],[6,9]], newInterval = [2,5]
输出: [[1,5],[6,9]]

示例 2:

输入: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出: [[1,2],[3,10],[12,16]]
解释: 这是因为新的区间 [4,8][3,5],[6,7],[8,10] 重叠。

示例 3:

输入: intervals = [], newInterval = [5,7]
输出: [[5,7]]

一、思路

插入区间 题目中有一个比较重要的信息:

  • 区间列表中的区间是无重复的、按左边界升序

这说明我们只需要找到合适的地方进行合并插入即可

区间列表与新区间共有以下三种情况:

  1. 新区间在区间列表中某个区间的左侧,且不重叠

image.png

  1. 新区间在区间列表中某个区间的右侧,且不重叠

image.png

  1. 新区间与区间列表有重叠

image.png

那么这三种情况该如何处理呢?

在遍历区间列表的过程中,对新区间的处理的方式如下所示:

  1. 新区间与当前区间有交集:更新新区间的左右边界
  2. 新区间在当前区间的右侧:将当前区间加入结果集
  3. 新区间在当前区间左侧:如果之前合并过,将新区间加入结果集,再将当前区间加入结果集。

举个例子

此处以示例2中的 intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] 作为例子

  1. 左边界 l = newInterval[0] = 4,右边界 r = newInterval[1] = 8
  2. 开始遍历,当 i=0 时,intervals[0] 与左右边界无交集,且新区间在当前区间的右侧,故将当前区间 intervals[0] 加入结果集
  3. i=1 时,intervals[1] 与左右边界有交集,更新左右边界,l = 3,右边界 r = 8
  4. i=2 时,intervals[2] 与左右边界有交集,更新左右边界,l = 3,右边界 r = 8
  5. i=3 时,intervals[3] 与左右边界有交集,更新左右边界,l = 3,右边界 r = 10
  6. i=4 时,intervals[4] 与左右边界无交集,且新区间在当前区间的左侧,故将新区间 [3, 10] 加入结果集,再将当前区间 [12, 16] 加入结果集
  7. 最后返回结果集即可

二、实现

实现代码

实现代码与思路保持一致

    public int[][] insert(int[][] intervals, int[] newInterval) {
        List<int[]> ret = new ArrayList<>();
        int l = newInterval[0];
        int r = newInterval[1];
        boolean merged = false; // 是否合并过
        for (int[] interval : intervals) {
            if (interval[0] > r) {  // 当前区间在新区间右侧
                if (!merged) {  // 如果没合并过
                    ret.add(new int[]{l, r});
                    merged = true;
                }
                ret.add(interval);
            } else if (interval[1] < l) {   // 当前区间在新区间左侧
                ret.add(interval);
            } else {    // 有交集
                l = Math.min(l, interval[0]);
                r = Math.max(r, interval[1]);
            }
        }
        if (!merged) {  // 如果最后都没有放置过,则将新区间放到最后
            ret.add(new int[]{l, r});
        }
        return ret.toArray(new int[ret.size()][]);
    }

测试代码

    public static void main(String[] args) {
        int[][] intervals = {{1,3},{6,9}};
        int[] newInterval = {2, 5};
        new Number57().insert(intervals, newInterval);
    }

结果

image.png

三、总结

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