You have a list of time blocks — think busy slots on a calendar, each a [start, end] pair. Some of them overlap or butt up against each other, and you want one clean view: the consolidated stretches of busy time, with no two blocks touching. Implement intervalsCombineOverlapping(intervals), which takes a list of intervals in any order and returns a new list of merged, non-overlapping intervals sorted by start.
// intervals: Array<[number, number]>
// A list of [start, end] pairs. CLOSED intervals: each one includes both
// endpoints, so [1, 3] covers 1, 3, and everything between. The list may be
// in any order; start <= end for every pair.
// returns: Array<[number, number]>
// A NEW array of merged, non-overlapping intervals, sorted by start.
// Two intervals merge if they overlap OR merely touch at an endpoint:
// [1, 3] and [3, 5] become [1, 5].
function intervalsCombineOverlapping(intervals): Array<[number, number]>;
// An overlapping set collapses; the gap-separated blocks stay apart.
intervalsCombineOverlapping([
[1, 3],
[2, 6],
[8, 10],
[15, 18],
]);
// → [[1, 6], [8, 10], [15, 18]]
// [1, 3] and [2, 6] overlap → [1, 6]; the other two have gaps, so they stay.
// Touching at an endpoint counts as overlapping (closed intervals).
intervalsCombineOverlapping([
[1, 3],
[3, 5],
]);
// → [[1, 5]]
// They share the point 3, so they merge into one block.
// Unsorted input with a chain only reachable after sorting.
intervalsCombineOverlapping([
[1, 4],
[5, 6],
[2, 5],
]);
// → [[1, 6]]
// Sorted, this is [1,4],[2,5],[5,6]: [1,4]+[2,5]=[1,5], then +[5,6]=[1,6].
[1, 3] covers everything from 1 to 3 inclusive.[1, 3] and [3, 5] — merge into [1, 5]. A one-unit gap like [1, 2] and [3, 4] does not merge; 2 and 3 are distinct points.[start, end] pair should change — return fresh arrays.start > end, or non-numeric coordinates — those are out of scope.