Non Overlapping Intervals Minimum Removal in DSA Go - Time & Space Complexity
We want to find out how long it takes to remove the fewest intervals so none overlap.
How does the time needed grow as the number of intervals grows?
Analyze the time complexity of the following code snippet.
func eraseOverlapIntervals(intervals [][]int) int {
if len(intervals) == 0 {
return 0
}
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][1] < intervals[j][1]
})
count := 0
end := intervals[0][1]
for i := 1; i < len(intervals); i++ {
if intervals[i][0] < end {
count++
} else {
end = intervals[i][1]
}
}
return count
}
This code sorts intervals by their end time, then counts how many overlap to remove the minimum.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Sorting the intervals and then looping through them once.
- How many times: Sorting takes multiple comparisons (depends on n log n), then one loop runs n-1 times.
Sorting grows faster than looping as input grows.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 * log(10) + 10 = 43 |
| 100 | About 100 * log(100) + 100 = 700 |
| 1000 | About 1000 * log(1000) + 1000 = 10000 |
Pattern observation: Operations grow a bit faster than the input size because of sorting.
Time Complexity: O(n log n)
This means as the number of intervals grows, the time needed grows a bit faster than just counting them because of sorting.
[X] Wrong: "The loop alone decides the time, so it is O(n)."
[OK] Correct: Sorting the intervals takes more time than the loop, so it dominates the total time.
Understanding how sorting affects time helps you explain your solution clearly and shows you know what matters most in performance.
"What if the intervals were already sorted by end time? How would the time complexity change?"
Practice
Non Overlapping Intervals Minimum Removal problem?Solution
Step 1: Understand the problem goal
The problem asks to remove as few intervals as possible so that no two intervals overlap.Step 2: Clarify what non-overlapping means
Non-overlapping means intervals do not share any common points except possibly at the boundary.Final Answer:
To remove the minimum number of intervals so that the remaining intervals do not overlap -> Option AQuick Check:
Minimum removal = no overlaps [OK]
- Thinking the goal is to merge intervals
- Confusing maximum overlaps with minimum removals
- Sorting intervals without removing any
Solution
Step 1: Identify sorting by end time
We need to sort intervals by their end time ascending to apply greedy approach.Step 2: Check the Go sort.Slice syntax
sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] }) sorts by intervals[i][1] < intervals[j][1], which is correct for end time ascending.Final Answer:
sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] }) -> Option CQuick Check:
Sort by end time ascending = sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] }) [OK]
- Sorting by start time instead of end time
- Sorting in descending order by mistake
- Using wrong slice indices
package main
import (
"fmt"
"sort"
)
func eraseOverlapIntervals(intervals [][]int) int {
if len(intervals) == 0 {
return 0
}
sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] })
count := 0
end := intervals[0][1]
for i := 1; i < len(intervals); i++ {
if intervals[i][0] < end {
count++
} else {
end = intervals[i][1]
}
}
return count
}
func main() {
intervals := [][]int{{1,3},{2,4},{3,5}}
fmt.Println(eraseOverlapIntervals(intervals))
}Solution
Step 1: Sort intervals by end time
Sorted intervals: [1,3], [2,4], [3,5]Step 2: Count overlaps
Start with end=3. Interval [2,4] starts at 2 < 3, so count=1. Interval [3,5] starts at 3 ≥ 3, update end=5.Final Answer:
1 -> Option BQuick Check:
One overlap removed = 1 [OK]
- Not sorting intervals before counting
- Counting intervals that do not overlap
- Incorrectly updating end pointer
func eraseOverlapIntervals(intervals [][]int) int {
if len(intervals) == 0 {
return 0
}
sort.Slice(intervals, func(i, j int) bool { return intervals[i][1] < intervals[j][1] })
count := 0
end := intervals[0][1]
for i := 1; i < len(intervals); i++ {
if intervals[i][0] < end {
count++
} else {
end = intervals[i][0]
}
}
return count
}Solution
Step 1: Check sorting and end update
Sorting by end time is correct, but updating end incorrectly with intervals[i][0] is wrong.Step 2: Explain why end update is wrong
End should track the end time of last non-overlapping interval, so intervals[i][1] is correct.Final Answer:
Updating end with intervals[i][0] instead of intervals[i][1] causes wrong comparisons -> Option AQuick Check:
End must be interval end, not start [OK]
- Confusing interval start and end when updating end
- Ignoring empty slice check
- Misunderstanding sorting impact
[[1,2],[2,3],[3,4],[1,3]], what is the minimum number of intervals to remove to make the rest non-overlapping?Solution
Step 1: Sort intervals by end time
Sorted intervals: [1,2], [1,3], [2,3], [3,4]Step 2: Count overlaps and removals
Start end=2. Interval [1,3] starts at 1 < 2, count=1. Interval [2,3] starts at 2 ≥ 2, update end=3. Interval [3,4] starts at 3 ≥ 3, update end=4.Final Answer:
1 -> Option DQuick Check:
One removal needed = 1 [OK]
- Not sorting intervals before counting
- Removing more intervals than needed
- Miscounting overlaps with boundary intervals
Ready to prove it?
Pass the test and this pattern moves unknown
