这是我参与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]]
一、思路
插入区间 题目中有一个比较重要的信息:
- 区间列表中的区间是无重复的、按左边界升序的
这说明我们只需要找到合适的地方进行合并或插入即可
区间列表与新区间共有以下三种情况:
- 新区间在区间列表中某个区间的左侧,且不重叠
- 新区间在区间列表中某个区间的右侧,且不重叠
- 新区间与区间列表有重叠
那么这三种情况该如何处理呢?
在遍历区间列表的过程中,对新区间的处理的方式如下所示:
- 新区间与当前区间有交集:更新新区间的左右边界
- 新区间在当前区间的右侧:将当前区间加入结果集
- 新区间在当前区间左侧:如果之前合并过,将新区间加入结果集,再将当前区间加入结果集。
举个例子
此处以示例2中的 intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] 作为例子
- 左边界
l = newInterval[0] = 4,右边界r = newInterval[1] = 8 - 开始遍历,当
i=0时,intervals[0]与左右边界无交集,且新区间在当前区间的右侧,故将当前区间intervals[0]加入结果集 i=1时,intervals[1]与左右边界有交集,更新左右边界,l = 3,右边界r = 8i=2时,intervals[2]与左右边界有交集,更新左右边界,l = 3,右边界r = 8i=3时,intervals[3]与左右边界有交集,更新左右边界,l = 3,右边界r = 10i=4时,intervals[4]与左右边界无交集,且新区间在当前区间的左侧,故将新区间[3, 10]加入结果集,再将当前区间[12, 16]加入结果集- 最后返回结果集即可
二、实现
实现代码
实现代码与思路保持一致
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);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥