给你一个 无重叠的 , 按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
示例 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]]
示例 4:
输入: intervals = [[1,5]], newInterval = [2,3]
输出: [[1,5]]
示例 5:
输入: intervals = [[1,5]], newInterval = [2,7]
输出: [[1,7]]
提示:
0 <= intervals.length <= 10^4intervals[i].length == 20 <= intervals[i][0] <= intervals[i][1] <= 10^5intervals根据intervals[i][0]按 升序 排列newInterval.length == 20 <= newInterval[0] <= newInterval[1] <= 10^5
思路
对于区间 s1 = [l1,r1]和区间 s2 = [l2,r2], 如果他们没有交集,满足 r1<l2,此时 s1 在 s2 的右侧,或 r2<l1,此时 s1 在 s2 的左侧,如果两个条件都不满足,则 s1 和 s2 必相交,合并区间为 [min(l1, l2), max(r1, r2)]。
我们遍历 intervals, 找到 i,满足 intervals[i][1] >= newInterval[0] , 判断 intervals[i] 是否相交,
- 如果相交,合并区间,继续判断是否和下一个区间相交,直到不相交为止,删除原先相交的区间,并插入合并后的区间 。
- 如果不相交,在
intervals[i]之前插入newInterval
在查找i时,由于区间是有序的,可以使用二分查找加快查找速度。
解题
/**
* @param {number[][]} intervals
* @param {number[]} newInterval
* @return {number[][]}
*/
var insert = function (intervals, newInterval) {
const bf = (num, key) => {
let l = 0;
let r = intervals.length - 1;
while (l <= r) {
const mid = (l + r) >> 1;
if (intervals[mid][key] === num) {
r = mid;
break;
} else if (intervals[mid][key] < num) {
l = mid + 1;
} else {
r = mid - 1;
}
}
return r;
};
let l = bf(newInterval[0], 0);
let r = bf(newInterval[1], 1);
if (l >= 0 && intervals[l][1] >= newInterval[0]) {
newInterval[0] = intervals[l][0];
} else {
l++;
}
if (r < intervals.length - 1 && intervals[r + 1][0] <= newInterval[1]) {
newInterval[1] = intervals[r + 1][1];
r++;
}
intervals.splice(l, r - l + 1, newInterval);
return intervals;
};
module.exports = insert;