Given an array of N intervals in the form of (start[i], end[i]), where start[i] is the starting point of the interval and end[i] is the ending point of the interval, return the minimum number of intervals that need to be removed to make the remaining intervals non-overlapping.
Input : Intervals = [ [1, 2] , [2, 3] , [3, 4] ,[1, 3] ]
Output : 1
Explanation : You can remove the interval [1, 3] to make the remaining interval non overlapping.
Input : Intervals = [ [1, 3] , [1, 4] , [3, 5] , [3, 4] , [4, 5] ]
Output : 2
Explanation : You can remove the intervals [1, 4] and [3, 5] and the remaining intervals becomes non overlapping.
Input : Intervals = [ [1, 10] , [1, 4] , [3, 8] , [3, 4] , [4, 5] ]
#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
// Comparator function to compare intervals based on their ending times
bool static comp(vector<int>& val1, vector<int>& val2) {
return val1[1] < val2[1];
}
public:
// Function to count the maximum number of non-overlapping intervals
int MaximumNonOverlappingIntervals(vector<vector<int>>& intervals) {
// Sort the intervals based on their ending times
sort(intervals.begin(), intervals.end(), comp);
// Get total number of intervals
int n = intervals.size();
// Initialize counter
int cnt = 1;
// Keep track of the ending time
int lastEndTime = intervals[0][1];
// Iterate through all intervals
for (int i = 1; i < n; i++) {
/* Check if the starting time of the current
interval is greater than or equal to
the ending time of the last
selected interval */
if (intervals[i][0] >= lastEndTime) {
// Increment counter
cnt++;
// Update the ending time
lastEndTime = intervals[i][1];
}
}
return n - cnt;
}
};
// Main function
int main() {
vector<vector<int>> intervals = {{0, 5}, {3, 4}, {1, 2}, {5, 9}, {7, 9}};
// Creating an object of solution class
Solution solution;
// Function call to get the maximum non-overlapping intervals
int ans = solution.MaximumNonOverlappingIntervals(intervals);
cout << "Maximum Non-Overlapping Intervals: " << ans << endl;
return 0;
}
import java.util.*;
class Solution {
// Comparator function to compare intervals based on their ending times
public static int comp(int[] val1, int[] val2) {
// Compare the ending times of the intervals
return Integer.compare(val1[1], val2[1]);
}
// Function to count the maximum number of non-overlapping intervals
public int MaximumNonOverlappingIntervals(int[][] intervals) {
// Sort the intervals based on their ending times
Arrays.sort(intervals, Solution::comp);
// Get total number of intervals
int n = intervals.length;
// Initialize counter
int cnt = 1;
// Keep track of the ending time
int lastEndTime = intervals[0][1];
// Iterate through all intervals
for (int i = 1; i < n; i++) {
/* Check if the starting time of the current
interval is greater than or equal to
the ending time of the last
selected interval */
if (intervals[i][0] >= lastEndTime) {
// Increment counter
cnt++;
// Update the ending time
lastEndTime = intervals[i][1];
}
}
return n-cnt;
}
}
// Main class
class Main {
public static void main(String[] args) {
Solution obj = new Solution();
int[][] intervals = {{0, 5}, {3, 4}, {1, 2}, {5, 9}, {7, 9}};
for (int i = 0; i < intervals.length; i++) {
System.out.println("Interval " + (i + 1) + " Start: " + intervals[i][0] + " End: " + intervals[i][1]);
}
int ans = obj.MaximumNonOverlappingIntervals(intervals);
System.out.println("Maximum Non-Overlapping Intervals: " + ans);
}
}
class Solution:
# Function to compare intervals based on ending times
@staticmethod
def comp(val1, val2):
# Compare the ending times of the intervals
return val1[1] < val2[1]
# Function to count the maximum number of non-overlapping intervals
def MaximumNonOverlappingIntervals(self, intervals):
# Sort the intervals based on their ending times
intervals.sort(key=lambda x: x[1])
# Get total number of intervals
n = len(intervals)
# Initialize counter
cnt = 1
# Keep track of the ending time
last_end_time = intervals[0][1]
# Iterate through all intervals
for i in range(1, n):
# Check if the starting time of the current
# interval is greater than or equal to the
# ending time of the last selected interval
if intervals[i][0] >= last_end_time:
# Increment counter
cnt += 1
# Update the ending time
last_end_time = intervals[i][1]
return n-cnt
# Example usage
if __name__ == "__main__":
obj = Solution()
intervals = [[0, 5], [3, 4], [1, 2], [5, 9], [7, 9]]
for i, interval in enumerate(intervals):
print(f"Interval {i + 1} Start: {interval[0]} End: {interval[1]}")
ans = obj.MaximumNonOverlappingIntervals(intervals)
print(f"Maximum Non-Overlapping Intervals: {ans}")
class Solution {
// Comparator function to compare intervals based on their ending times
static comp(a, b) {
// Compare the ending times of the intervals
return a[1] - b[1];
}
// Function to count the maximum number of non-overlapping intervals
MaximumNonOverlappingIntervals(intervals) {
// Sort the intervals based on their ending times
intervals.sort(Solution.comp);
// Get total number of intervals
const n = intervals.length;
// Initialize counter
let cnt = 1;
// Keep track of the ending time
let lastEndTime = intervals[0][1];
// Iterate through all intervals
for (let i = 1; i < n; i++) {
/* Check if the starting time of
the current interval is greater
than or equal to the ending time of
the last selected interval */
if (intervals[i][0] >= lastEndTime) {
// Increment counter
cnt++;
// Update the ending time
lastEndTime = intervals[i][1];
}
}
return n-cnt;
}
}
// Example usage
const obj = new Solution();
const intervals = [[0, 5], [3, 4], [1, 2], [5, 9], [7, 9]];
intervals.forEach((interval, i) => {
console.log(`Interval ${i + 1} Start: ${interval[0]} End: ${interval[1]}`);
});
const ans = obj.MaximumNonOverlappingIntervals(intervals);
console.log(`Maximum Non-Overlapping Intervals: ${ans}`);
Q: Why sort by end time instead of start time?
A: Sorting by end time ensures that you select the interval that leaves the most space for subsequent intervals, maximizing the number of non-overlapping intervals that can be included.
Q: What if two intervals have the same end time?
A: If two intervals share the same end time, their order doesn’t matter because overlapping will still be avoided by comparing the start times.
Q: How would you handle dynamic updates to the intervals?
A: For dynamic scenarios, such as adding or removing intervals, consider using a balanced binary search tree or interval tree to efficiently manage overlapping intervals.
Q: What if you wanted to minimize the total "overlap time" instead of removing intervals?
A: Modify the algorithm to calculate and minimize the sum of overlapping durations rather than the count of intervals removed.