Insert New Interval
You are given an array of non-overlapping intervals intervals where intervals[i] = [start_i, end_i] represents the start and the end time of the ith interval. intervals is initially sorted in ascending order by start_i.
You are given another interval newInterval = [start, end].
Insert newInterval into intervals such that intervals is still sorted in ascending order by start_i and also intervals still does not have any overlapping intervals. You may merge the overlapping intervals if needed.
Return intervals after adding newInterval.
Note: Intervals are non-overlapping if they have no common point. For example, [1,2] and [3,4] are non-overlapping, but [1,2] and [2,3] are overlapping.
Example 1:
Input: intervals = [[1,3],[4,6]], newInterval = [2,5]
Output: [[1,6]]
Example 2:
Input: intervals = [[1,2],[3,5],[9,10]], newInterval = [6,7]
Output: [[1,2],[3,5],[6,7],[9,10]]
Constraints:
0 <= intervals.length <= 1000
newInterval.length == intervals[i].length == 2
0 <= start <= end <= 1000
Solution
With binary search, we can find the last interval that its right endpoint is less than left endpoint of new interval, noting the index as pos_le
, then find the first interval that its left endpoint is greater than right endpoint of new interval, noting the index as pos_ri
.
The new interval must be placed between pos_le
and pos_ri
interval. If pos_le==pos_ri
, it means the new interval is included by an existing interval, we just need to return original intervals
. Otherwise, insert one new interval with endpoints [min(newInterval[0], intervals[pos_le+1][0]), max(newInterval[1], intervals[pos_ri-1][1])]
.
Code
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
intervals = [[-1, -1]] + intervals[:] + [[1001, 1001]]
le = 0
ri = len(intervals)-1
pos_le = -1
while le <= ri:
mid = (le+ri)//2
if intervals[mid][1] < newInterval[0]:
pos_le = mid
le = mid+1
else:
ri = mid-1
le = 0
ri = len(intervals)-1
pos_ri = -1
while le <= ri:
mid = (le+ri)//2
if intervals[mid][0] <= newInterval[1]:
le = mid+1
else:
pos_ri = mid
ri = mid-1
print(pos_le, pos_ri)
if pos_le == pos_ri:
return intervals[1:-1]
return intervals[1:pos_le+1] + [[min(newInterval[0], intervals[pos_le+1][0]), max(newInterval[1], intervals[pos_ri-1][1])]] + intervals[pos_ri:-1]
Also, we can solve it without binary search
class Solution:
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
res = []
for i in range(len(intervals)):
if newInterval[1] < intervals[i][0]:
res.append(newInterval)
return res + intervals[i:]
elif newInterval[0] > intervals[i][1]:
res.append(intervals[i])
else:
newInterval = [
min(newInterval[0], intervals[i][0]),
max(newInterval[1], intervals[i][1]),
]
res.append(newInterval)
return res