Exit
  1. Learn
  2. Check
  3. Solve
  4. Reflect

Extend or start fresh

Walk the sorted list keeping a result list, like a person tidying a timetable. For each interval, look at the last merged one. If the new start is at or before its end, stretch that end to the larger of the two ends.

If not, there is a gap, so add the interval as a new group.

Starts before the open group ends? stretch its end to the larger end.
Otherwise: a gap: add the interval as a new group.
In code
merged = []
for start, end in sorted(intervals):
    if merged and start <= merged[-1][1]:
        last = merged[-1]
        last[1] = max(last[1], end)
    else:
        merged.append([start, end])
return merged
intervals = [[8, 10], [1, 3], [2, 6], [9, 12]]
123456789101112[8, 10][1, 3][2, 6][9, 12]answer

Sort by start: [1, 3], [2, 6], [8, 10], [9, 12]. Start the answer with [1, 3].

Move 1 of 4

Trace it

Sorted: [1, 3], [2, 6], [8, 10], [9, 12]. Start with [1, 3]. Next, 2 starts before 3 ends, so it stretches to [1, 6]. Then 8 starts after 6, a gap, so add [8, 10]. Then 9 starts before 10 ends, so it stretches to [8, 12].

Result: [[1, 6], [8, 12]].

Take the larger end: [1, 10] then [2, 3] must stay [1, 10].
One pass: each interval is looked at once after the sort.