题目描述
给你一个 无重叠的 ,按照区间起始端点排序的区间列表 intervals
,其中 intervals[i]
= [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals
按照 starti 升序排列。同样给定一个区间 newInterval
= [starti, endi] 表示另一个区间的开始和结束。
在 intervals
中插入区间 newInterval
,使得 intervals
依然按照 starti 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。
返回插入之后的 intervals
。
注意 你不需要原地修改 intervals
。你可以创建一个新数组然后返回它。
示例 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] 重叠。
提示:
- 0 <=
intervals.length
<= 104 - intervals[i].length == 2
- 0 <= starti <= endi <= 105
- intervals 根据 starti 按 升序 排列
- newInterval.length == 2
- 0 <= start <= end <= 105
解题方法
模拟
这道题的主要思路就是怎么合并区间。我们可以先看一下下面这张图。
可以看出,黄色区间是需要插入的区间。合并区间时,我们只需要将插入区间与原始区间重叠的部分进行合并,未重叠的区间保持不变。
区间合并时我们会遇到以下几种情况,我们需要分别处理。
- 当插入区间
newInterval
的左边界 大于 区间列表中intervals[i]
的右边界时,新区间列表直接插入intervals[i]
元素。 - 当插入区间
newInterval
的右边界 小于 区间列表中intervals[i]
的左边界时,新区间列表先插入newInterval
元素,再插入intervals[i]
元素。 - 当插入区间
newInterval
与区间列表中intervals[i]
重叠时,需要记录最左边界和最右边界,直到与后面的区间元素不再重合时,将合并后的新区间插入新区间列表。
接下来就是按照上述思路,实现代码编写。
java代码
public int[][] insert(int[][] intervals, int[] newInterval) {
int left = newInterval[0];
int right = newInterval[1];
// 判断新区间newInterval合并后是否被插入过,若newInterval合并完成后在intervals末尾,需要将合并后的区间插入一次
boolean placed = false;
List<int[]> ansList = new ArrayList<int[]>();
for (int[] interval : intervals) {
if (interval[0] > right) {
// 在插入区间的右侧且无交集
if (!placed) {
ansList.add(new int[]{left, right});
placed = true;
}
ansList.add(interval);
} else if (interval[1] < left) {
// 在插入区间的左侧且无交集
ansList.add(interval);
} else {
// 与插入区间有交集,计算它们的并集
left = Math.min(left, interval[0]);
right = Math.max(right, interval[1]);
}
}
if (!placed) {
ansList.add(new int[]{left, right});
}
return ansList.toArray(new int[ansList.size()][]);
}
复杂度分析
时间复杂度:
O
(
N
)
O(N)
O(N),需要遍历一次数组。
空间复杂度:
O
(
1
)
O(1)
O(1),除了存储结果的空间外,只需要额外的常数空间。
相似题目
- 个人公众号
- 个人小游戏