Open In App

Minimum removals required to make ranges non-overlapping

Last Updated : 23 Apr, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a list of ranges with starting and end value, the task is to find the minimum number of ranges that are required to be removed to make remaining ranges non-overlapping. Examples:

Input : input = {{1, 2}, {4, 7}, {3, 8}} Output : 1 Explanation: Removal of {3, 8} makes {{1, 2} and {4, 7}} non-overlapping. Input : input = {{ 10, 20 }, { 10, 20 } , { 10, 20 }} Output : 2 Explanation: Removal of [10, 20] makes the remaining ranges non-overlapping. Input : input = {{1, 2}, {5, 10}, {18, 35}, {40, 45}} Output : 0 Explanation:All ranges are already non-overlapping.

Approach 1 : (Sort basis on Starting Values) 

  • Sort the ranges by their starting values.
  • Traverse through the ranges and check if any range has a starting point less than the ending point of the previous (ie. there is an overlap).
  • Remove the range with greater ending point.

Below code is the implementation of the above approach:

C++
#include <bits/stdc++.h>
using namespace std;

int minRemovals(vector<vector<int> >& ranges)
{

    int size = ranges.size(), rem = 0;

    if (size <= 1)
        return 0;

    // Sort by minimum starting point
    sort(ranges.begin(), ranges.end(),
        [](const vector<int>& a, const vector<int>& b)
                    { return a[0] < b[0]; });

    int end = ranges[0][1];
    for (int i = 1; i < ranges.size(); i++) {

        // If the current starting point is less than
        // the previous interval's ending point
        // (ie. there is an overlap)
        if (ranges[i][0] < end) {
            // increase rem
            rem++;
            // Remove the interval
            // with the higher ending point
            end = min(ranges[i][1], end);
        }
        else
            end = ranges[i][1];
    }

    return rem;
}

// Driver code
int main()
{
    vector<vector<int> > input = { { 19, 25 },
                        { 10, 20 }, { 16, 20 } };
    cout << minRemovals(input) << endl;
}
Java
//Java equivalent of above code
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main {
  public static int minRemovals(List<int[]> ranges) {
    int size = ranges.size(), rem = 0;

    if (size <= 1)
      return 0;

    // Sort by minimum starting point
    Collections.sort(ranges, new Comparator<int[]>() {
      @Override
      public int compare(int[] o1, int[] o2) {
        return o1[0] - o2[0];
      }
    });

    int end = ranges.get(0)[1];
    for (int i = 1; i < ranges.size(); i++) {
      // If the current starting point is less than
      // the previous interval's ending point
      // (ie. there is an overlap)
      if (ranges.get(i)[0] < end) {
        // increase rem
        rem++;
        // Remove the interval
        // with the higher ending point
        end = Math.min(ranges.get(i)[1], end);
      } else
        end = ranges.get(i)[1];
    }

    return rem;
  }

  // Driver code
  public static void main(String[] args) {
    List<int[]> input = new ArrayList<int[]>();
    input.add(new int[] { 19, 25 });
    input.add(new int[] { 10, 20 });
    input.add(new int[] { 16, 20 });
    System.out.println(minRemovals(input));
  }
}
Python3
def minRemovels (ranges):

    size = len(ranges)
    rem = 0

    # Sort by minimum starting point
    ranges.sort()

    end = ranges[0][1]
    for i in range(1, size):

        # If the current starting point is less
        # than the previous interval's ending
        # point (ie. there is an overlap)
        if (ranges[i][0] < end):

            # Increase rem
            rem += 1

            # Remove the interval
            # with the higher ending point
            end = min(ranges[i][1], end)
            
        else:
            end = ranges[i][1]

    return rem

# Driver Code
if __name__ == '__main__':
    
    Input = [ [ 19, 25 ],
            [ 10, 20 ],
            [ 16, 20 ] ]
                
    print(minRemovels(Input))

# This code is contributed by himanshu77
C#
using System;
using System.Linq;

class GFG {
  static int MinRemovals(int[][] ranges)
  {
    int size = ranges.Length;
    int rem = 0;

    // Sort by minimum starting point
    Array.Sort(ranges, (a, b) => a[0] - b[0]);

    int end = ranges[0][1];
    for (int i = 1; i < size; i++)
    {
      
      // If the current starting point is less than
      // the previous interval's ending point (ie.
      // there is an overlap)
      if (ranges[i][0] < end) 
      {
        
        // Increase rem
        rem += 1;

        // Remove the interval with the higher
        // ending point
        end = Math.Min(ranges[i][1], end);
      }
      else {
        end = ranges[i][1];
      }
    }

    return rem;
  }

  // Driver code
  public static void Main(string[] args)
  {
    int[][] ranges
      = new int[][] { new int[] { 19, 25 },
                     new int[] { 10, 20 },
                     new int[] { 16, 20 } };


    // Function call
    Console.WriteLine(MinRemovals(ranges));
  }
}

// This code is contributed by phasing17
Javascript
// JavaScript implementation to find the minimum
// removals required to make intervals non-overlapping
function minRemovels(ranges) {
    var size = ranges.length;
    var rem = 0;

    // Sort by minimum starting point
    ranges.sort(function(a, b) {
        return a[0] - b[0];
    });
    
    var end = ranges[0][1];
    for (var i = 1; i < size; i++) {
        // If the current starting point is less than the previous interval's ending
        // point (ie. there is an overlap)
        if (ranges[i][0] < end) {
            // Increase rem
            rem += 1;
    
            // Remove the interval with the higher ending point
            end = Math.min(ranges[i][1], end);
    
        } else {
            end = ranges[i][1];
        }
    }
    
    return rem;
}

// Driver Code
var ranges = [[19, 25], [10, 20], [16, 20]];
console.log(minRemovels(ranges));

// This code is contributed by phasing17

Output
2

Time Complexity: O(n log n)
Auxiliary Space: O(1) as no extra space has been used.

Approach 2 : (Sort basis on Ending Values)

  • The idea still remains the same as approach 1 as the main work is to find out the overlap point and keep a greater ending time.
  • Sort the array on basis of ending values.
  • Increase the count (i.e. remove the range with greater end point) if any overlap condition is found.
  • else update for a greater end point.

Below is the code for better understanding.

C++
#include <bits/stdc++.h>
using namespace std;

// comparator function
bool comp(vector<int>& v1, vector<int>& v2)
{
    return v1[1] < v2[1];
}

int minRemovals(vector<vector<int> >& ranges)
{
    int size = ranges.size(), rem = 0;

    if (size <= 1)
        return 0;

    // Sort by minimum ending point
    sort(ranges.begin(), ranges.end(), comp);

    int end = ranges[0][1];

    for (int i = 1; i < ranges.size(); i++) {

        // if there is an overlap
        // increase the count
        if (ranges[i][0] < end)
            rem++;

        // else increment the ending point
        else
            end = ranges[i][1];
    }

    // return the ans
    return rem;
}

// Driver code
int main()
{
    vector<vector<int> > input
        = { { 19, 25 }, { 10, 20 }, { 16, 20 } };
    cout << minRemovals(input) << endl;
}

// this code is contributed by Rajdeep Mallick (rajdeep999)
Java
import java.util.*;

class Main {

    // Comparator function
    static boolean comp(ArrayList<Integer> v1, ArrayList<Integer> v2) {
        return v1.get(1) < v2.get(1);
    }

    static int minRemovals(ArrayList<ArrayList<Integer>> ranges) {
        int size = ranges.size(), rem = 0;

        if (size <= 1)
            return 0;

        // Sort by minimum ending point
        Collections.sort(ranges, (a, b) -> a.get(1).compareTo(b.get(1)));

        int end = ranges.get(0).get(1);

        for (int i = 1; i < ranges.size(); i++) {

            // if there is an overlap, increase the count
            if (ranges.get(i).get(0) < end)
                rem++;
            // else increment the ending point
            else
                end = ranges.get(i).get(1);
        }

        // return the ans
        return rem;
    }

    // Driver code
    public static void main(String[] args) {
        ArrayList<ArrayList<Integer>> input = new ArrayList<>();
        input.add(new ArrayList<>(Arrays.asList(19, 25)));
        input.add(new ArrayList<>(Arrays.asList(10, 20)));
        input.add(new ArrayList<>(Arrays.asList(16, 20)));

        System.out.println(minRemovals(input));
    }
}
Python3
# Comparator function
def comp(v1, v2):
    return v1[1] < v2[1]

def min_removals(ranges):
    size = len(ranges)
    rem = 0

    if size <= 1:
        return 0

    # Sort by minimum ending point
    ranges.sort(key=lambda x: x[1])

    end = ranges[0][1]

    for i in range(1, len(ranges)):
        # If there is an overlap, increase the count
        if ranges[i][0] < end:
            rem += 1
        # Else, increment the ending point
        else:
            end = ranges[i][1]

    # Return the answer
    return rem

# Driver code
if __name__ == "__main__":
    input_ranges = [[19, 25], [10, 20], [16, 20]]
    print(min_removals(input_ranges))

Output
2

Time Complexity: O(n log n)
Auxiliary Space: O(1) as no extra space has been used.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads