Card 07/ 08
Practice: Fitting a New Booking Into a Day
A day's bookings are sorted and do not overlap: add one more and merge whatever it touches, in one pass and without sorting again.
Inserting one interval into a sorted list that has no overlaps uses the merge's overlap test in a single pass, with no sort. A workshop's bench is booked [1, 2], [4, 5], [6, 8], [9, 11] and [13, 14], sorted by start, with closed times that merge when they touch. A new booking, [7, 10], arrives. Return the day's bookings with the new one added and anything it overlaps merged, in O(n) time.
Show the answer and a solution
The day becomes [1, 2], [4, 5], [6, 11] and [13, 14]. The pass has three phases. Copy every booking that ends before the new one starts. Then, while a booking starts at or before the new one's end, they overlap: widen the new booking to the smaller start and the larger end. Then append the widened booking and copy the rest. Here [6, 8] and [9, 11] both overlap [7, 10] and widen it to [6, 11].
before
1 3 5 7 9 11 13
[1, 2] ====
[4, 5] ====
[6, 8] ======
[9, 11] ======
[13, 14] ====
new ========
after
1 3 5 7 9 11 13
[1, 2] ====
[4, 5] ====
[6, 11] ============
[13, 14] ====The listing inserts [7, 10], then [3, 3], which overlaps nothing and lands between [1, 2] and [4, 5].
def insert(bookings: list[list[int]], new: list[int]) -> list[list[int]]:
result: list[list[int]] = []
start, end = new
i = 0
while i < len(bookings) and bookings[i][1] < start:
result.append(bookings[i])
i += 1
while i < len(bookings) and bookings[i][0] <= end:
start = min(start, bookings[i][0])
end = max(end, bookings[i][1])
i += 1
result.append([start, end])
result.extend(bookings[i:])
return result
bookings = [[1, 2], [4, 5], [6, 8], [9, 11], [13, 14]]
print("after inserting [7, 10]:", insert(bookings, [7, 10]))
print("after inserting [3, 3]: ", insert(bookings, [3, 3]))after inserting [7, 10]: [[1, 2], [4, 5], [6, 11], [13, 14]]
after inserting [3, 3]: [[1, 2], [3, 3], [4, 5], [6, 8], [9, 11], [13, 14]]Each booking is read once, so the pass is O(n) time and O(n) space for the result. Appending [7, 10] and running the full merge also works, but sorts again for O(n log n), throwing away the order the list already had.
← → move through sections and cards