[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 by starti 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 }

 

扫描线相关题目

LeetCode 题目总结

posted @ 2019-11-01 11:18  CNoodle  阅读(476)  评论(0编辑  收藏  举报