[LeetCode] 57. Insert Interval
You are given an array of non-overlapping intervals intervals
where intervals[i] = [starti, endi]
represent the start and the end of the ith
interval and intervals
is sorted in ascending order by starti
. You are also given an interval newInterval = [start, end]
that represents the start and end of another interval.
Insert newInterval
into intervals
such that intervals
is still sorted in ascending order by starti
and intervals
still does not have any overlapping intervals (merge overlapping intervals if necessary).
Return intervals
after the insertion.
Example 1:
Input: intervals = [[1,3],[6,9]], newInterval = [2,5] Output: [[1,5],[6,9]]
Example 2:
Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] Output: [[1,2],[3,10],[12,16]] Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
Constraints:
0 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 105
intervals
is sorted bystarti
in ascending order.newInterval.length == 2
0 <= start <= end <= 105
NOTE: input types have been changed on April 15, 2019. Please reset to default code definition to get new method signature.
插入区间。
给你一个 无重叠的 ,按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/insert-interval
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这题也是用到扫描线思想,题意是给了一个二维数组intervals,存放了一堆区间[start, end],又给了一个新的区间newInterval,需要把newInterval塞入intervals。(以下用第二个example举例)思路是
- 遍历intervals,把跟newInterval没有交集的interval先加入结果集,这里是用每个interval的end去跟newInterval的start作比较,所有满足条件subinterval[1] < newInterval[0]的subinterval会被直接加入结果集
- 例子,比如[4, 8]一直都是和每个subinterval的end比较,比如和[1, 2]的2比较,和[3, 5]的5比较
- newInterval开始跟某些intervals有交集了,此时此刻需要开始merge。判断newInterval和某个interval有交集的方法是判断是否有某个interval的start小于newInterval的end。
- 但是为什么代码里直接给出的是intervals[i][0] <= newInterval[1]呢?这个判断条件不是很直观。这个判断条件实际包含了好几种情况
- intervals[i]的左边界 <= newInterval的左边界一样的情况下,谁的左边界小就用谁的左边界,谁的右边界大就用谁的右边界。这里相当于是修改某一个interval的边界,应该很好理解。比如[3, 5]和[4, 8]的处理。
- 但是处理完[3, 5]和[4, 8]得到[3, 8],你发现后面的[6, 7]实际上还要接着一块merge,所以这里只能用while循环,一直往后看,看是否还有更多的subinterval等待被merge。在while循环跳出后,才把这个新的interval加入结果集。
- 这样做同时也可以克服类似这样的corner case,intervals = [[1, 2]], newInterval = [4, 5]。实际两者是没有交集的,但是有了这个while,就可以确保[4, 5]也被加入结果集。
- 遍历剩下的intervals,无条件加入结果集,因为他们跟newInterval一定也没有交集。如何知道我可以开始遍历剩下的intervals了呢?把这个条件取反即可,intervals[i][0] <= newInterval[1],得到intervals[i][0] > newInterval[1],也就是某一个subinterval的开始已经大于要merge的interval的右边界了,这时如果还没遍历完,剩下的subinterval就可以直接加入结果集了。
时间O(n)
空间O(n)
JavaScript实现
1 /** 2 * @param {number[][]} intervals 3 * @param {number[]} newInterval 4 * @return {number[][]} 5 */ 6 var insert = function(intervals, newInterval) { 7 // corner case 8 if (newInterval === null) { 9 return intervals; 10 } 11 12 // normal case 13 let res = []; 14 let i = 0; 15 // all the intervals before newInterval 16 while (i < intervals.length && intervals[i][1] < newInterval[0]) { 17 res.push(intervals[i]); 18 i++; 19 } 20 21 // compare newInterval with the interval might overlap 22 while (i < intervals.length && intervals[i][0] <= newInterval[1]) { 23 newInterval[0] = Math.min(intervals[i][0], newInterval[0]); 24 newInterval[1] = Math.max(intervals[i][1], newInterval[1]); 25 i++; 26 } 27 res.push(newInterval); 28 29 // all the intervals after newInterval 30 while (i < intervals.length) { 31 res.push(intervals[i]); 32 i++; 33 } 34 return res; 35 };
Java实现
1 class Solution { 2 public int[][] insert(int[][] intervals, int[] newInterval) { 3 // corner case 4 if (intervals == null) { 5 return intervals; 6 } 7 8 // normal case 9 int len = intervals.length; 10 List<int[]> res = new ArrayList<>(); 11 int i = 0; 12 // intervals before 13 while (i < len && intervals[i][1] < newInterval[0]) { 14 res.add(intervals[i]); 15 i++; 16 } 17 18 // merge current interval 19 while (i < len && intervals[i][0] <= newInterval[1]) { 20 newInterval[0] = Math.min(newInterval[0], intervals[i][0]); 21 newInterval[1] = Math.max(newInterval[1], intervals[i][1]); 22 i++; 23 } 24 res.add(newInterval); 25 26 // intervals after 27 while (i < len) { 28 res.add(intervals[i]); 29 i++; 30 } 31 return res.toArray(new int[res.size()][]); 32 } 33 }