Merge Overlapping Intervals in DSA C - Time & Space Complexity
We want to understand how the time needed to merge overlapping intervals changes as the number of intervals grows.
Specifically, how does the work increase when we have more intervals to merge?
Analyze the time complexity of the following code snippet.
int compare(const void *a, const void *b) {
return ((int (*)[2])a)[0][0] - ((int (*)[2])b)[0][0];
}
// Merge overlapping intervals in an array
void mergeIntervals(int intervals[][2], int n) {
// Sort intervals by start time
qsort(intervals, n, sizeof(intervals[0]), compare);
int index = 0; // stores index of last merged interval
for (int i = 1; i < n; i++) {
if (intervals[index][1] >= intervals[i][0]) {
if (intervals[index][1] < intervals[i][1])
intervals[index][1] = intervals[i][1];
} else {
index++;
intervals[index][0] = intervals[i][0];
intervals[index][1] = intervals[i][1];
}
}
}
This code sorts intervals by their start time, then merges overlapping ones by updating the end time or moving to the next interval.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Sorting the intervals and then one loop to merge them.
- How many times: Sorting takes multiple comparisons depending on n, and the loop runs once through all intervals.
Sorting grows faster than just looping, so it dominates the time.
| 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: As input grows, sorting cost grows faster than the simple loop, so total time grows roughly like n times 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 sorting takes extra work.
[X] Wrong: "Merging intervals only takes O(n) time because we just loop once."
[OK] Correct: Before merging, we must sort intervals, which takes more time than just looping, so total time is more than O(n).
Understanding this time complexity helps you explain why sorting is important before merging and shows you can analyze combined steps clearly.
"What if the intervals were already sorted? How would the time complexity change?"
Practice
Merge Overlapping Intervals problem?Solution
Step 1: Understand the problem goal
The problem asks to merge intervals that overlap, so they become one continuous interval without gaps.Step 2: Identify the correct description
Combine all intervals that overlap into one continuous interval correctly describes merging overlapping intervals into one combined interval.Final Answer:
Combine all intervals that overlap into one continuous interval -> Option CQuick Check:
Merge overlapping intervals = Combine overlaps [OK]
- Confusing merging with sorting only
- Counting intervals instead of merging
- Ignoring overlaps
Solution
Step 1: Identify sorting criteria for merging
Intervals must be sorted by their start time to merge correctly.Step 2: Match sorting function
qsort(intervals, n, sizeof(Interval), compareStart); usescompareStartwhich sorts by start time, correct for merging.Final Answer:
qsort(intervals, n, sizeof(Interval), compareStart); -> Option AQuick Check:
Sort by start time = qsort with compareStart [OK]
- Sorting by end time instead of start time
- Using C++ sort syntax in C code
- Sorting by interval length
Intervals = [[1,3], [2,6], [8,10], [15,18]] // After sorting by start time // Merge overlapping intervals // Print merged intervals
Solution
Step 1: Sort intervals by start time
Intervals are already sorted: [1,3], [2,6], [8,10], [15,18].Step 2: Merge overlapping intervals
[1,3] and [2,6] overlap, merge to [1,6]. Others do not overlap.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 non-overlapping intervals
- Incorrectly merging intervals with gaps
Interval merged[100];
int m = 0;
merged[0] = intervals[0];
for (int i = 1; i < n; i++) {
if (intervals[i].start <= merged[m].end) {
merged[m].end = intervals[i].end;
} else {
m++;
merged[m] = intervals[i];
}
}Solution
Step 1: Analyze interval merging logic
When intervals overlap, end should be max of both ends, not just assigned.Step 2: Identify incorrect update
Code sets previous end to current end without max check, causing wrong merges.Final Answer:
It incorrectly updates the end of the previous interval without checking max end -> Option BQuick Check:
Use max end when merging intervals [OK]
- Assigning end without max check
- Using strict < instead of <= for touching intervals
- Wrong loop start index
Solution
Step 1: Understand touching intervals as overlapping
Intervals that share boundary points merge: [1,4] and [4,5] merge to [1,5], then with [5,6] to [1,6].Step 2: Merge intervals accordingly
After merging first three intervals, [7,8] remains separate.Final Answer:
[[1,6], [7,8]] -> Option DQuick Check:
Touching intervals merge into one [OK]
- Not merging touching intervals
- Merging all intervals incorrectly
- Ignoring boundary overlap condition
Ready to prove it?
Pass the test and this pattern moves unknown
