Sort intervals by start time. Then merge sequentially.
Walk through sorted intervals. If current interval overlaps with the last merged interval (current.start <= lastMerged.end), extend lastMerged.end to max(lastMerged.end, current.end).
Otherwise, current interval starts a new non-overlapping region. Add it to results.