Merge Overlapping Intervals in DSA Javascript - Time & Space Complexity
We want to understand how the time needed to merge overlapping intervals changes as the number of intervals grows.
How does the code handle more intervals and how long does it take?
Analyze the time complexity of the following code snippet.
function mergeIntervals(intervals) {
intervals.sort((a, b) => a[0] - b[0]);
const merged = [];
for (const interval of intervals) {
if (!merged.length || merged[merged.length - 1][1] < interval[0]) {
merged.push(interval);
} else {
merged[merged.length - 1][1] = Math.max(merged[merged.length - 1][1], interval[1]);
}
}
return merged;
}
This code sorts intervals by start time, then merges any that overlap into one.
- Primary operation: Sorting the intervals array.
- How many times: Sorting takes multiple comparisons, roughly proportional to n log n where n is the number of intervals.
- Secondary operation: One loop through all intervals to merge them, running n times.
As the number of intervals grows, sorting takes more time, growing faster than just going through the list once.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log(10) ≈ 33 operations for sorting + 10 for merging |
| 100 | About 100 * log(100) ≈ 664 operations for sorting + 100 for merging |
| 1000 | About 1000 * log(1000) ≈ 9966 operations for sorting + 1000 for merging |
Pattern observation: Sorting dominates and grows faster than the simple loop, so total time grows roughly like n log n.
Time Complexity: O(n log n)
This means the time to merge intervals grows a bit faster than just the number of intervals because of sorting, but still much better than checking every pair.
[X] Wrong: "The merging loop is the slowest part, so the time is O(n)."
[OK] Correct: Sorting the intervals first takes more time than the loop, so the overall time depends mostly on sorting, not just the loop.
Understanding how sorting affects the time helps you explain your solution clearly and shows you know what part of your code costs the most time.
"What if the intervals were already sorted? How would the time complexity change?"
Practice
Merge Overlapping Intervals algorithm?Solution
Step 1: Understand the problem goal
The algorithm aims to merge intervals that share any overlapping range into a single interval.Step 2: Identify the correct purpose
Among the options, only combining overlapping intervals matches the goal.Final Answer:
To combine all intervals that overlap into one continuous interval -> Option BQuick Check:
Merge overlapping intervals = combine overlaps [OK]
- Confusing merging with sorting intervals
- Thinking it splits intervals instead of merging
- Assuming it counts intervals instead of merging
Solution
Step 1: Identify sorting key for merging
We must sort intervals by their start time, which is the first element in each interval array.Step 2: Choose correct sort function
The correct syntax isintervals.sort((a, b) => a[0] - b[0])to sort ascending by start time.Final Answer:
intervals.sort((a, b) => a[0] - b[0]) -> Option AQuick Check:
Sort by start time = a[0] - b[0] [OK]
- Sorting by end time instead of start time
- Sorting in descending order
- Using wrong array indices for sorting
const intervals = [[1,3],[2,6],[8,10],[15,18]];
function merge(intervals) {
intervals.sort((a,b) => a[0] - b[0]);
const merged = [];
for (const interval of intervals) {
if (!merged.length || merged[merged.length-1][1] < interval[0]) {
merged.push(interval);
} else {
merged[merged.length-1][1] = Math.max(merged[merged.length-1][1], interval[1]);
}
}
return merged;
}
console.log(merge(intervals));Solution
Step 1: Sort intervals by start time
Sorted intervals: [[1,3],[2,6],[8,10],[15,18]] (already sorted)Step 2: Merge overlapping intervals
Merge [1,3] and [2,6] into [1,6]. Others remain separate.Final Answer:
[[1,6],[8,10],[15,18]] -> Option AQuick Check:
Merged intervals = [[1,6],[8,10],[15,18]] [OK]
- Not merging overlapping intervals
- Merging intervals incorrectly by extending wrong boundaries
- Returning original intervals without merging
function merge(intervals) {
intervals.sort((a,b) => a[0] - b[0]);
const merged = [];
for (const interval of intervals) {
if (merged.length === 0 || merged[merged.length-1][1] <= interval[0]) {
merged.push(interval);
} else {
merged[merged.length-1][1] = Math.max(merged[merged.length-1][1], interval[1]);
}
}
return merged;
}Solution
Step 1: Analyze the overlap condition
The condition uses <= which treats touching intervals as non-overlapping.Step 2: Correct the condition for merging
Using < instead of <= allows intervals that touch at the boundary to merge correctly.Final Answer:
The condition should use < instead of <= to detect overlap -> Option CQuick Check:
Overlap check needs <, not <= [OK]
- Using <= causes missing merges for touching intervals
- Not sorting intervals before merging
- Incorrectly updating merged intervals
[[1,4],[4,5],[7,9],[8,10]], what is the merged output if intervals that touch at boundaries are considered overlapping?Solution
Step 1: Sort intervals by start time
Sorted intervals: [[1,4],[4,5],[7,9],[8,10]] (already sorted)Step 2: Merge touching and overlapping intervals
[1,4] and [4,5] touch, so merge to [1,5]. [7,9] and [8,10] overlap, merge to [7,10].Final Answer:
[[1,5],[7,10]] -> Option DQuick Check:
Touching intervals merge = [[1,5],[7,10]] [OK]
- Not merging intervals that only touch at boundaries
- Merging all intervals incorrectly into one
- Leaving intervals separate despite overlap
Ready to prove it?
Pass the test and this pattern moves unknown
