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.
Two intervals are considered overlapping if they share at least one point.
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.
Note that you don't need to modify intervals in-place. You can make a new array and return it.
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
Solutions
Solution 1: Sorting + Interval Merging
Thinking
The first idea is to insert \(\textit{newInterval}\) into the list and reuse ordinary interval merging. \(n \le 10^4\), so an \(O(n \log n)\) sort will pass.
The list is already sorted and non-overlapping, but reusing merge-intervals is the least extra code: append, sort, merge. Correct; it just ignores the given order.
We can first add the new interval newInterval to the interval list intervals, and then merge according to the regular method of interval merging.
The time complexity is \(O(n \times \log n)\), and the space complexity is \(O(n)\). Here, \(n\) is the number of intervals.
Solution 1 sorts again and throws away the existing order, paying an extra \(\log n\).
What it lacks is a single pass: write a current interval if it lies entirely left of the new one; if it lies entirely right, insert the new interval first; otherwise widen the new interval's ends. Append at the end if it was never inserted. Linear, no sort.
We can traverse the interval list intervals, let the current interval be interval, and there are three situations for each interval:
The current interval is on the right side of the new interval, that is, \(newInterval[1] < interval[0]\). At this time, if the new interval has not been added, then add the new interval to the answer, and then add the current interval to the answer.
The current interval is on the left side of the new interval, that is, \(interval[1] < newInterval[0]\). At this time, add the current interval to the answer.
Otherwise, it means that the current interval and the new interval intersect. We take the minimum of the left endpoint of the current interval and the left endpoint of the new interval, and the maximum of the right endpoint of the current interval and the right endpoint of the new interval, as the left and right endpoints of the new interval, and then continue to traverse the interval list.
After the traversal, if the new interval has not been added, then add the new interval to the answer.
The time complexity is \(O(n)\), where \(n\) is the number of intervals. Ignoring the space consumption of the answer array, the space complexity is \(O(1)\).