Add a booking to a sorted list of separate blocks

Greedy choices and intervals Mid-level Python 3.13+ Reviewed By Best Latest Apps

Predict the output

What does this print?

Python 3.13
blocks, new = [[1, 2], [3, 5], [6, 7], [8, 10]], [4, 8]
left = [b for b in blocks if b[1] < new[0]]
right = [b for b in blocks if b[0] > new[1]]
mid = [b for b in blocks if b not in left and b not in right]
lo = min([new[0]] + [b[0] for b in mid])
hi = max([new[1]] + [b[1] for b in mid])
merged = [lo, hi]
print(left + [merged] + right)

Options

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A [[1, 2], [3, 10]]

Right: [3, 5], [6, 7] and [8, 10] all touch [4, 8].

Only the middle group changes; the blocks on either side are copied as they are, which keeps the work linear.

Why not the others?
  • B [[1, 2], [3, 8], [8, 10]]. [8, 10] touches the new booking at 8.
  • C [[1, 2], [4, 8]]. The absorbed blocks widen the new one.

30-second answer

Three phases in one pass: copy the blocks that end before the new one starts; absorb every block that starts at or before the new one's end by widening it; then copy the rest. O(n) time and O(n) space for the output, no sort needed because the input is already sorted.

Practise saying it · 30 s. No recording, just a timer

Explain inserting into merged blocks.

Say your answer out loud, then check which of these points you covered:

  • Copy before
  • Absorb overlapping
  • Copy after

Deep dive

Using the sorted input is the point; re-sorting would be O(n log n).

A binary search can find where phase two starts, but copying keeps it O(n) anyway.

Keep the same touching rule as the merge question.

Python solution Ran on Python 3.13.5 · mypy --strict
Python 3.13
def add_booking(blocks: list[list[int]],
                new: list[int]) -> list[list[int]]:
    out: list[list[int]] = []
    start, end = new
    i = 0
    while i < len(blocks) and blocks[i][1] < start:  # wholly before
        out.append(blocks[i])
        i += 1
    while i < len(blocks) and blocks[i][0] <= end:  # touches: absorb
        start, end = min(start, blocks[i][0]), max(end, blocks[i][1])
        i += 1
    out.append([start, end])
    return out + blocks[i:]

Common mistakes

  • Re-sorting everything.
  • Forgetting blocks fully inside the new booking.

Senior take & follow-ups

Name the three phases before coding.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you do it in place?

    Show hint

    Find the range of absorbed blocks with two binary searches, then replace that slice.

  2. What about removing a time range?

    Show hint

    Same three phases, but blocks in the middle are trimmed or split.

What each operation costs: Merge Sort · Quick Sort

From the author

DSA Master - Data & Algorithms

Free on iPhone and iPad: watch 50+ data structures and algorithms step through animations, run the code in the playground, and try the daily challenge.

Suggest a fix if something here is wrong or out of date.