题目
给你一个 无重叠的 ,按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
示例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] 重叠。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/insert-interval
思路
这种题凭空想象容易懵逼,最好是有例子去实际的模拟一下过程,然后抽象出里边的共同点。
其实两个示例已经给的挺好了。
我们能看出来这个区间要么能直接插入,和谁都没有重叠,要么就需要和左边或者右边合并,甚至需要合并多个区间。
而鉴于这个数组是有序的且不重叠的,那么我们肯定是能够通过一次遍历就能找到这个要插入的区间所重叠的区间,并且在这个过程中把重叠的区间进行整合。
这里有几个点需要考虑:
- 因为最终的数组长度已经不确定了,那么需要在遍历过程中用一个list结构来进行收集所有的区间
- 什么时候能把一个区间加入到list里呢?一定是当前这个区间和要插入的区间没有重叠。也就是要插入的区间要么完全在比较区间的左侧、要么在比较区间的右侧。
- 如果要插入的区间已经整合完成了,那么后边是没有必要再进行计算了的,直接收集即可,所以需要一个标记来记录整合完成。
- 如何进行区间整合呢?我们可以记录下要插入的区间,在遍历过程中,如果有区间和它有交集,改变区间左右范围,继续往后进行判断,直到这个区间整合完成。
- 什么时候整合完成呢?就是这个区间的右侧在下一个区间的左侧,或者已经结束遍历。
code
import java.util.ArrayList;
import java.util.List;
class Solution {
public int[][] insert(int[][] intervals, int[] newInterval) {
List<int[]> collect = new ArrayList<>();
boolean needCal = true;
int left = newInterval[0];
int right = newInterval[1];
for (int i = 0; i < intervals.length; i++) {
int[] currentInterval = intervals[i];
if (needCal) {
if (right < currentInterval[0]) {
collect.add(new int[]{left, right});
collect.add(currentInterval);
needCal = false;
} else if (left > currentInterval[1]){
collect.add(currentInterval);
} else {
left = Math.min(left, currentInterval[0]);
right = Math.max(right, currentInterval[1]);
}
} else {
collect.add(currentInterval);
}
}
if (needCal) {
collect.add(new int[]{left, right});
}
return collect.toArray(new int[collect.size()][]);
}
}
时间复杂度:O(n)
空间复杂度:O(n)
耗时:32分钟