LeetCodee

435. Non-overlapping Intervals

Jump to Solution: Python Java C++ JavaScript C#

Problem Description

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.

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⁵
  • intervals[i].length == 2
  • -5 * 10⁴ <= starti < endi <= 5 * 10⁴

Solution

Python Solution

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals:
            return 0
            
        # Sort intervals by end time
        intervals.sort(key=lambda x: x[1])
        
        non_overlapping = 1
        end = intervals[0][1]
        
        # Count non-overlapping intervals
        for i in range(1, len(intervals)):
            if intervals[i][0] >= end:
                non_overlapping += 1
                end = intervals[i][1]
        
        return len(intervals) - non_overlapping

Time Complexity: O(n log n)

Where n is the number of intervals. The sorting step takes O(n log n) time.

Space Complexity: O(1)

Only using a constant amount of extra space.

Java Solution

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals == null || intervals.length == 0) {
            return 0;
        }
        
        // Sort intervals by end time
        Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1]));
        
        int nonOverlapping = 1;
        int end = intervals[0][1];
        
        // Count non-overlapping intervals
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] >= end) {
                nonOverlapping++;
                end = intervals[i][1];
            }
        }
        
        return intervals.length - nonOverlapping;
    }
}

Time Complexity: O(n log n)

Where n is the number of intervals. The sorting step takes O(n log n) time.

Space Complexity: O(1)

Only using a constant amount of extra space.

C++ Solution

class Solution {
public:
    int eraseOverlapIntervals(vector>& intervals) {
        if (intervals.empty()) {
            return 0;
        }
        
        // Sort intervals by end time
        sort(intervals.begin(), intervals.end(), 
             [](const vector& a, const vector& b) {
                 return a[1] < b[1];
             });
        
        int nonOverlapping = 1;
        int end = intervals[0][1];
        
        // Count non-overlapping intervals
        for (int i = 1; i < intervals.size(); i++) {
            if (intervals[i][0] >= end) {
                nonOverlapping++;
                end = intervals[i][1];
            }
        }
        
        return intervals.size() - nonOverlapping;
    }
};

Time Complexity: O(n log n)

Where n is the number of intervals. The sorting step takes O(n log n) time.

Space Complexity: O(1)

Only using a constant amount of extra space.

JavaScript Solution

/**
 * @param {number[][]} intervals
 * @return {number}
 */
var eraseOverlapIntervals = function(intervals) {
    if (!intervals.length) {
        return 0;
    }
    
    // Sort intervals by end time
    intervals.sort((a, b) => a[1] - b[1]);
    
    let nonOverlapping = 1;
    let end = intervals[0][1];
    
    // Count non-overlapping intervals
    for (let i = 1; i < intervals.length; i++) {
        if (intervals[i][0] >= end) {
            nonOverlapping++;
            end = intervals[i][1];
        }
    }
    
    return intervals.length - nonOverlapping;
};

Time Complexity: O(n log n)

Where n is the number of intervals. The sorting step takes O(n log n) time.

Space Complexity: O(1)

Only using a constant amount of extra space.

C# Solution

public class Solution {
    public int EraseOverlapIntervals(int[][] intervals) {
        if (intervals == null || intervals.Length == 0) {
            return 0;
        }
        
        // Sort intervals by end time
        Array.Sort(intervals, (a, b) => a[1].CompareTo(b[1]));
        
        int nonOverlapping = 1;
        int end = intervals[0][1];
        
        // Count non-overlapping intervals
        for (int i = 1; i < intervals.Length; i++) {
            if (intervals[i][0] >= end) {
                nonOverlapping++;
                end = intervals[i][1];
            }
        }
        
        return intervals.Length - nonOverlapping;
    }
}

Time Complexity: O(n log n)

Where n is the number of intervals. The sorting step takes O(n log n) time.

Space Complexity: O(1)

Only using a constant amount of extra space.

Approach Explanation

The solution uses a greedy approach:

  1. Key Insights:
    • Sort by end time
    • Greedy selection
    • Interval tracking
    • Overlap detection
  2. Algorithm Steps:
    • Sort intervals
    • Track end time
    • Count non-overlapping
    • Calculate removals

Implementation Details:

  • Sorting logic
  • Interval comparison
  • Counter management
  • Result calculation

Optimization Insights:

  • End time sorting
  • Single pass
  • Early termination
  • Space efficiency

Edge Cases:

  • Empty array
  • Single interval
  • Complete overlap
  • No overlap