Given an array of 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.
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 <= 105
intervals[i].length == 2
-5 * 104 <= starti < endi <= 5 * 104
Greedy Algorithms
bool compare(vector<int> & a, vector<int> & b);
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(),compare );
int maxNum=0;
int end =intervals[0][0];
for(int i=0;i<intervals.size();i++)
{
if(end<= intervals[i][0])
{
maxNum++;
end = intervals[i][1];
//cout<< " [ "<< curinterval[0] << " , "<< curinterval[1]<<" ]"<< endl;
}
}
return intervals.size() - maxNum;
}
};
bool compare(vector<int> & a, vector<int> & b)
{
if(a[1]==b[1])
{
return (a[1] - a[0])< (b[1] - b[0]);
}
return a[1]<b[1];
}
let’s break down each step of the code:
-
Sorting Function (
compare
):- The
compare
function is used as a custom comparator for sorting the intervals. - It first compares the end points of two intervals (
a
andb
). - If the end points are equal, it compares the lengths of the intervals and returns true if the length of interval
a
is less than the length of intervalb
. - Otherwise, it returns true if the end point of interval
a
is less than the end point of intervalb
.
- The
-
Greedy Algorithm (
eraseOverlapIntervals
):- The function begins by sorting the intervals using the custom comparator (
compare
). - It initializes variables:
maxNum
to count non-overlapping intervals, andend
to store the end point of the current considered interval. - It then iterates through the sorted intervals.
- For each interval, if its start point is greater than or equal to the current
end
:- Increments
maxNum
(counting a non-overlapping interval). - Updates
end
to the end point of the current interval.
- Increments
- Finally, the function returns the difference between the total number of intervals and the non-overlapping intervals (
intervals.size() - maxNum
).
- The function begins by sorting the intervals using the custom comparator (
-
Time Complexity:
- The sorting operation using
std::sort
has a time complexity of O(n log n), where n is the number of intervals. - The subsequent iteration through the sorted intervals is linear, O(n).
- Therefore, the overall time complexity of the algorithm is dominated by the sorting step and is O(n log n).
- The sorting operation using
In summary, the algorithm sorts the intervals based on their end points and then iterates through the sorted intervals, greedily selecting non-overlapping intervals. The sorting step ensures that the intervals are processed in a way that maximizes the selection of non-overlapping intervals.
bool compare(vector<int> & a, vector<int> & b);
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(),compare );
int maxNum=0;
int begin =intervals[0][1];
for(int i=0;i<intervals.size();i++)
{
if(begin>= intervals[i][1])
{
maxNum++;
begin = intervals[i][0];
cout<< " [ "<< intervals[i][0] << " , "<< intervals[i][1]<<" ]"<< endl;
}
}
return intervals.size() - maxNum;
}
};
bool compare(vector<int> & a, vector<int> & b)
{
return a[0]>b[0];
}
The approach uses a greedy strategy and involves sorting intervals based on their start points in descending order.
Algorithm Overview:
The core idea is to process intervals in reverse order, starting with the one that has the largest start point. Let’s break down the algorithm step by step:
Sorting Function (compare):
We employ a custom comparator function, compare, to sort intervals in descending order based on their start points. The function compares the start points, ensuring that intervals are arranged from largest to smallest.
cpp
Copy code
bool compare(vector& a, vector& b) {
return a[0] > b[0];
}
Greedy Algorithm (eraseOverlapIntervals):
Sorting: We sort the intervals using the custom comparator in the eraseOverlapIntervals function.
cpp
Copy code
sort(intervals.begin(), intervals.end(), compare);
Initialization: Initialize variables maxNum to count non-overlapping intervals and begin to store the end point of the first interval.
cpp
Copy code
int maxNum = 0;
int begin = intervals[0][1];
Iterating Through Intervals: Iterate through the sorted intervals in reverse order.
cpp
Copy code
for(int i = 0; i < intervals.size(); i++) {
// Check for non-overlapping intervals
if (begin >= intervals[i][1]) {
// Update count and endpoint
maxNum++;
begin = intervals[i][0];
// Print the non-overlapping interval
cout << " [ " << intervals[i][0] << " , " << intervals[i][1] << " ]" << endl;
}
}
Result: Return the difference between the total number of intervals and the non-overlapping ones.
cpp
Copy code
return intervals.size() - maxNum;
Time Complexity:
The sorting step dominates the time complexity, resulting in O(n log n), where n is the number of intervals. The subsequent linear iteration through the sorted intervals contributes to the overall efficiency of the algorithm.
Conclusion:
This greedy approach leverages sorting in descending order to simplify the identification of non-overlapping intervals. The algorithm’s simplicity, coupled with its efficiency, makes it a viable solution for minimizing the number of intervals to be removed.
And what’s the time complexity of this algorithm?
You: The sorting operation is O(n log n), and the subsequent iteration through the sorted intervals is linear, so the overall time complexity is O(n log n).
参
考文献
https://edutechlearners.com/download/Introduction_to_algorithms-3rd%20Edition.pdf
https://leetcode.com/problems/non-overlapping-intervals/solutions/3785409/beat-s-100-c-java-python-beginner-friendly