Problem
Given an array of intervals intervals
where intervals[i] = [starti, endi]
, return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.
Note that intervals which only touch at a point are non-overlapping. For example, [1, 2]
and [2, 3]
are non-overlapping.
Examples
Example 1:
Input: intervals = [[1,2],[2,3],[3,4],[1,3]]
Output: 1
Explanation: [1,3] can be removed and the rest of the intervals are non-overlapping.
Example 2:
Input: intervals = [[1,2],[1,2],[1,2]]
Output: 2
Explanation: You need to remove two [1,2] to make the rest of the intervals non-overlapping.
Example 3:
Input: intervals = [[1,2],[2,3]]
Output: 0
Explanation: You don't need to remove any of the intervals since they're already non-overlapping.
Constraints
1 <= intervals.length <= 10^5
intervals[i].length == 2
-5 * 10^4 <= starti < endi <= 5 * 10^4
Solution
Method 1 - Sorting by Start of Interval
We can sort the intervals based on their starting times. Track prevEnd
from the previous interval. When comparing two intervals, consider the smaller end value to minimize overlaps with subsequent intervals.
Code
Java
public class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
// Sort intervals by their start times
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
int prevEnd = intervals[0][1];
int count = 0;
for (int i = 1; i < intervals.length; i++) {
if (prevEnd > intervals[i][0]) {
count++;
prevEnd = Math.min(intervals[i][1], prevEnd);
} else {
prevEnd = intervals[i][1];
}
}
return count;
}
}
Python
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
# Sort intervals by their start times
intervals.sort(key=lambda x: x[0])
prev_end = intervals[0][1]
count = 0
for i in range(1, len(intervals)):
if prev_end > intervals[i][0]:
count += 1
prev_end = min(intervals[i][1], prev_end)
else:
prev_end = intervals[i][1]
return count
Complexity
- ⏰ Time complexity:
O(n log n)
for sorting the intervals. - 🧺 Space complexity: -
O(1)
for space as we use a constant amount of extra space (excluding input).
Method 2 - Sorting by End of Interval
Actually, the problem is similar to classic greedy problem - Interval Scheduling Problem where we are given a collection of intervals, find the maximum number of intervals that are non-overlapping".
Code
Java
public class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
if (intervals.length == 0) {
return 0;
}
// Sort intervals by their end times
Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1]));
int end = intervals[0][1];
int count = 1;
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] >= end) {
end = intervals[i][1];
count++;
}
}
return intervals.length - count;
}
}
Python
class Solution:
def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
if not intervals:
return 0
# Sort intervals by their end times
intervals.sort(key=lambda x: x[1])
end = intervals[0][1]
count = 1
for i in range(1, len(intervals)):
if intervals[i][0] >= end:
end = intervals[i][1]
count += 1
return len(intervals) - count
Complexity
- ⏰ Time complexity:
O(n log n)
for sorting the intervals. - 🧺 Space complexity:
O(1)
as only a constant amount of extra space is used (excluding input).