Insert Interval (medium)
Dry-run templates
This is the implementation of the solution provided for the problem posed in the Insert Interval (medium) lesson:
def insert(intervals, new_interval):merged = []i, start, end = 0, 0, 1# skip (and add to output) all intervals that come before the 'new_interval'while i < len(intervals) and intervals[i][end] < new_interval[start]:merged.append(intervals[i])i += 1# merge all intervals that overlap with 'new_interval'while i < len(intervals) and intervals[i][start] <= new_interval[end]:new_interval[start] = min(intervals[i][start], new_interval[start])new_interval[end] = max(intervals[i][end], new_interval[end])i += 1# insert the new_intervalmerged.append(new_interval)# add all the remaining intervals to the outputwhile i < len(intervals):merged.append(intervals[i])i += 1return mergeddef main():print("Intervals after inserting the new interval: " + str(insert([[1, 3], [5, 7], [8, 12]], [4, 6])))print("Intervals after inserting the new interval: " + str(insert([[1, 3], [5, 7], [8, 12]], [4, 10])))print("Intervals after inserting the new interval: " + str(insert([[2, 3], [5, 7]], [1, 4])))main()
Students may be encouraged to run through the provided solution with the following sample inputs:
Sample Input #1
intervals: [[1, 3], [5, 7], [8, 12],[13,14]]
new_intervals: [8, 10]
Iteration No. | Line No. | i | merged | intervals[i][start] | intervals[i][end] |
- | 2-3 | 0 | [] | - | - |
1 | 6-7 | 0 | [[1, 3]] | - | 3 |
1 | 8 | 1 | [[1, 3]] | - | 3 |
2 | 6-7 | 1 | [[1, 3], [5, 7]] | - | 7 |
2 | 8 | 2 | [[1, 3], [5, 7]] | - | 7 |
1 | 11-13 | 2 | [[1, 3], [5, 7]] | 8 | - |
1 | 14 | 3 | [[1, 3], [5, 7]] | 8 | - |
- | 17 | 3 | [[1, 3], [5, 7], [8, 12]] | - | - |
1 | 20-21 | 3 | [[1, 3], [5, 7], [8, 12], [13, 14]] | - | - |
1 | 22 | 4 | [[1, 3], [5, 7], [8, 12], [13, 14]] | - | - |
Sample Input #2
intervals: [[2, 3], [5, 7]]
new_interval: [1, 4]
Iteration No. | Line No. | i | merged | intervals[i][start] | intervals[i][end] |
- | 2-3 | 0 | [] | - | - |
1 | 11-13 | 0 | [] | 2 | - |
1 | 14 | 1 | [] | 2 | - |
- | 17 | 1 | [[1, 4]] | - | - |
1 | 20-21 | 1 | [[1, 4], [5, 7]] | - | - |
1 | 22 | 2 | [[1, 4], [5, 7]] | - | - |
Step-by-step solution construction
There are three main parts of the solution:
- Identify the intervals before the new interval
- Merge the intervals that overlap the new interval
- Append the intervals greater than the new interval to the final intervals
In the code below, we are identifying the intervals which end before the start time of the new interval.
On lines 8-12, we add intervals[i]
to the merged
list if intervals[i][end]
is less than new_interval[start]
def insert(intervals, new_interval):merged = []i, start, end = 0, 0, 1# skip (and add to output) all intervals that come before the 'new_interval'if(intervals[i][end] < new_interval[start]):print("Skip all the intervals that end before 'new_interval' starts.\nAdd these unchanged to the output list:")while i < len(intervals) and intervals[i][end] < new_interval[start]:print("\ti: " + str(i))print("\t\tintervals[i][end]: " + str(intervals[i][end]))print("\t\tnew_interval[start]: " + str(new_interval[start]))merged.append(intervals[i])print("\t\tMerged so far: "+ str(merged))i += 1return mergeddef main():intervals_arr = [[[1, 3], [5, 7], [8, 12], [13, 14], [15, 20]], [[1, 3], [5, 7], [8, 12], [13, 14]],[[1, 3], [5, 7], [8, 12]],[[2, 3], [5, 7]]]new_intervals = [[7, 8], [8, 10], [4, 10], [1, 4]]for i in range(len(intervals_arr)):print("Inserting interval " + str(new_intervals[i]) + " in the intervals array: " + str(intervals_arr[i]) )result = insert(intervals_arr[i],new_intervals[i])print("List with new interval inserted: " + str(result))print("-"*100 + "\n")main()
In the code below, we merge the intervals
that overlap the new interval and append the merged interval to the intervals occurring before it.
On lines 19-24, we update new_interval[start]
and new_interval[end]
if we find an interval that starts before new_interval[end]
.
On line 29, we append the newly constructed interval new_interval
to the merged array.
def insert(intervals, new_interval):merged = []i, start, end = 0, 0, 1# skip (and add to output) all intervals that come before the 'new_interval'if(intervals[i][end] < new_interval[start]):print("Skip all the intervals that end before 'new_interval' starts.\nAdd these unchanged to the output list:")while i < len(intervals) and intervals[i][end] < new_interval[start]:print("\ti: " + str(i))print("\t\tintervals[i][end]: " + str(intervals[i][end]))print("\t\tnew_interval[start]: " + str(new_interval[start]))merged.append(intervals[i])print("\t\tMerged so far: "+ str(merged))i += 1# merge all intervals that overlap with 'new_interval'if(intervals[i][start] <= new_interval[end]):print("Merge all intervals that overlap with 'new_interval':")while i < len(intervals) and intervals[i][start] <= new_interval[end]:print("\t\ti: " + str(i))print("\t\tintervals[i][start]: " + str(intervals[i][start]))print("\t\tnew_interval[end]: " + str(new_interval[end]))new_interval[start] = min(intervals[i][start], new_interval[start])new_interval[end] = max(intervals[i][end], new_interval[end])i += 1# insert the new_intervalprint("\tInsert modified 'new_interval' ", str(new_interval), ":", sep="")merged.append(new_interval)print("\t\tMerged so far: "+ str(merged))return mergeddef main():intervals_arr = [[[1, 3], [5, 7], [8, 12], [13, 14], [15, 20]], [[1, 3], [5, 7], [8, 12], [13, 14]],[[1, 3], [5, 7], [8, 12]],[[2, 3], [5, 7]]]new_intervals = [[7, 8], [8, 10], [4, 10], [1, 4]]for i in range(len(intervals_arr)):print("Inserting interval " + str(new_intervals[i]) + " in the intervals array: " + str(intervals_arr[i]) )result = insert(intervals_arr[i],new_intervals[i])print("List with new interval inserted: " + str(result))print("-"*100 + "\n")main()
The merged
array contains the initial intervals and new interval so far. Now, we have to append the remaining intervals from the original intervals
array.
In the code below, on lines 35-39, we append intervals[i]
to the merged
array.
def insert(intervals, new_interval):merged = []i, start, end = 0, 0, 1# skip (and add to output) all intervals that come before the 'new_interval'if(intervals[i][end] < new_interval[start]):print("Skip all the intervals that end before 'new_interval' starts.\nAdd these unchanged to the output list:")while i < len(intervals) and intervals[i][end] < new_interval[start]:print("\ti: " + str(i))print("\t\tintervals[i][end]: " + str(intervals[i][end]))print("\t\tnew_interval[start]: " + str(new_interval[start]))merged.append(intervals[i])print("\t\tMerged so far: "+ str(merged))i += 1# merge all intervals that overlap with 'new_interval'if(intervals[i][start] <= new_interval[end]):print("Merge all intervals that overlap with 'new_interval':")while i < len(intervals) and intervals[i][start] <= new_interval[end]:print("\t\ti: " + str(i))print("\t\tintervals[i][start]: " + str(intervals[i][start]))print("\t\tnew_interval[end]: " + str(new_interval[end]))new_interval[start] = min(intervals[i][start], new_interval[start])new_interval[end] = max(intervals[i][end], new_interval[end])i += 1# insert the new_intervalprint("\tInsert modified 'new_interval' ", str(new_interval), ":", sep="")merged.append(new_interval)print("\t\tMerged so far: "+ str(merged))# add all the remaining intervals to the outputif(i < len(intervals)):print("Add all the remaining intervals to the output:")while i < len(intervals):merged.append(intervals[i])print("\ti: " + str(i))print("\tMerged so far: "+ str(merged))i += 1return mergeddef main():intervals_arr = [[[1, 3], [5, 7], [8, 12], [13, 14], [15, 20]], [[1, 3], [5, 7], [8, 12], [13, 14]],[[1, 3], [5, 7], [8, 12]],[[2, 3], [5, 7]]]new_intervals = [[7, 8], [8, 10], [4, 10], [1, 4]]for i in range(len(intervals_arr)):print("Inserting interval " + str(new_intervals[i]) + " in the intervals array: " + str(intervals_arr[i]) )result = insert(intervals_arr[i],new_intervals[i])print("List with new interval inserted: " + str(result))print("-"*100 + "\n")main()