LC 57 - Insert Interval
Question
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.
Note that you don’t need to modify intervals in-place. You can make a new array and return it.
Example 1:
1
2
Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
Output: [[1,5],[6,9]]
Example 2:
1
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 <= 104intervals[i].length == 20 <= starti <= endi <= 105intervalsis sorted bystartiin ascending order.newInterval.length == 20 <= start <= end <= 105
Links
Question here and solution here
Solution
concept
The greedy solution requires us to iterate through intervals and check the interval for 3 conditions:
- if the
newIntervalis non-overlapping and before the currentinterval, then we just append the rest of theintervalsand return. check conditionnewInterval[1] < intervals[i][0] - if the
newIntervalis non-overlapping and after the currentinterval, then we append the currentintervalintoansfirst, but not returning, sincenewIntervalcould still overlap with intervals afterwards. check conditionnewInterval[0] > intervals[i][1] - if either the condition above is not true, then there is an overlap between
newIntervaland the currentinterval, we need to merge and modifynewInterval = [min(newInterval[0], intervals[i][0]), max(newInterval[1], intervals[i][1])]. Take note at the end we need to addans.append(newInterval)since if the modifiednewIntervalis the last interval, it wont be added. so we need to manually append it.
code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class Solution:
"""
greedy
"""
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
ans = []
for i in range(len(intervals)):
# if non-overlapping
# the rest of the intervals wont be overlapping with newInterval, just add the rest and return
if newInterval[1] < intervals[i][0]:
ans.append(newInterval)
return ans + intervals[i:]
# current interval is not overlapping with newInterval so it is safe to add to ans, but not return yet
elif newInterval[0] > intervals[i][1]:
ans.append(intervals[i])
# handle merging
else:
newInterval = [min(newInterval[0], intervals[i][0]), max(newInterval[1], intervals[i][1])]
# if the abv return nv executre, means newInterval is the last one
ans.append(newInterval)
return ans
class Solution:
"""
linear search
"""
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
n = len(intervals)
i = 0
res = []
# locate the start of the merge
while i < n and intervals[i][1] < newInterval[0]:
res.append(intervals[i])
i += 1
# merge
while i < n and newInterval[1] >= intervals[i][0]:
newInterval[0] = min(newInterval[0], intervals[i][0])
newInterval[1] = max(newInterval[1], intervals[i][1])
i += 1
res.append(newInterval)
# add the rest
while i < n:
res.append(intervals[i])
i += 1
return res
class Solution:
"""
binary search to locate the start of the merging
search on the start index
"""
def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
if not intervals:
return [newInterval]
n = len(intervals)
target = newInterval[0]
left, right = 0, n - 1
while left <= right:
mid = (left + right) // 2
if intervals[mid][0] < target:
left = mid + 1
else:
right = mid - 1
intervals.insert(left, newInterval)
res = []
for interval in intervals:
if not res or res[-1][1] < interval[0]:
res.append(interval)
else:
res[-1][1] = max(res[-1][1], interval[1])
return res
Complexity
time: $O(n)$
space: $O(n)$