Skip to content
Related Articles

Related Articles

Maximum number of intervals that an interval can intersect
  • Difficulty Level : Hard
  • Last Updated : 12 Mar, 2021

Given an array arr[] consisting of N intervals of the form of [L, R], where L, R denotes the start and end positions of the interval, the task is to count the maximum number of intervals that an interval can intersect with each other.

Examples:

Input: arr[] = {{1, 2}, {3, 4}, {2, 5}}
Output: 3
Explanation: The required set of intervals are {1, 2}, {2, 5}, {3, 4} as {2, 5} intersect all other intervals.

Input: arr[] = {{1, 3}, {2, 4}, {3, 5}, {8, 11}}
Output: 3
Explanation: The required set of intervals are {1, 3}, {2, 4}, {3, 5} as {2, 4} intersect all other intervals.

Naive Approach: The simplest approach is to traverse the array and for each interval, count the number of intervals it intersects using a nested loop. After checking for each interval, print the maximum number of intervals that an interval can intersect.



Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to count the maximum number
// of intervals that an interval
// can intersect
void findMaxIntervals(
    vector<pair<int, int> > v, int n)
{
    // Store the required answer
    int maxi = 0;
 
    // Traverse all the intervals
    for (int i = 0; i < n; i++) {
 
        // Store the number of
        // intersecting intervals
        int c = n;
 
        // Iterate in the range[0, n-1]
        for (int j = 0; j < n; j++) {
 
            // Check if jth interval lies
            // outside the ith interval
            if (v[i].second < v[j].first
                || v[i].first > v[j].second) {
                c--;
            }
        }
 
        // Update the overall maximum
        maxi = max(c, maxi);
    }
 
    // Print the answer
    cout << maxi;
}
 
// Driver Code
int main()
{
    vector<pair<int, int> > arr
        = { { 1, 2 },
            { 3, 4 },
            { 2, 5 } };
    int N = arr.size();
 
    // Function Call
    findMaxIntervals(arr, N);
 
    return 0;
}


Java




// Java implementation of the approach
import java.util.*;
class GFG
{
 
  static class Pair
  {
    int first, second;
    public Pair(int first, int second)
    {
      this.first = first;
      this.second = second;
    }
  }
 
  // Function to count the maximum number
  // of intervals that an interval
  // can intersect
  static void findMaxIntervals(ArrayList<Pair> v, int n)
  {
 
    // Store the required answer
    int maxi = 0;
 
    // Traverse all the intervals
    for (int i = 0; i < n; i++)
    {
 
      // Store the number of
      // intersecting intervals
      int c = n;
 
      // Iterate in the range[0, n-1]
      for (int j = 0; j < n; j++) {
 
        // Check if jth interval lies
        // outside the ith interval
        if (v.get(i).second < v.get(j).first
            || v.get(i).first > v.get(j).second) {
          c--;
        }
      }
 
      // Update the overall maximum
      maxi = Math.max(c, maxi);
    }
 
    // Print the answer
    System.out.print(maxi);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    ArrayList<Pair> arr = new ArrayList<>();
    arr.add(new Pair(1,2));
    arr.add(new Pair(3,4));
    arr.add(new Pair(2,5));
 
    int N = arr.size();
 
    // Function Call
    findMaxIntervals(arr, N);
  }
}
 
// This code is contributed by susmitakundugoaldnga.


Python3




# Python3 program for the above approach
 
# Function to count the maximum number
# of intervals that an interval
# can intersect
def findMaxIntervals(v, n) :
    
    # Store the required answer
    maxi = 0
     
    # Traverse all the intervals
    for i in range(n) :
    
        # Store the number of
        # intersecting intervals
        c = n
    
        # Iterate in the range[0, n-1]
        for j in range(n) :
    
            # Check if jth interval lies
            # outside the ith interval
            if (v[i][1] < v[j][0] or v[i][0] > v[j][1]) :
             
                c -= 1
    
        # Update the overall maximum
        maxi = max(c, maxi)
    
    # Print the answer
    print(maxi)
     
    # Driver code
arr = []
arr.append((1,2))
arr.append((3,4))
arr.append((2,5))
N = len(arr)
 
# Function Call
findMaxIntervals(arr, N)
 
# This code is contributed by divyeshrabadiya07.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG
{
     
    // Function to count the maximum number
    // of intervals that an interval
    // can intersect
    static void findMaxIntervals(List<Tuple<int, int> > v, int n)
    {
       
        // Store the required answer
        int maxi = 0;
       
        // Traverse all the intervals
        for (int i = 0; i < n; i++)
        {
       
            // Store the number of
            // intersecting intervals
            int c = n;
       
            // Iterate in the range[0, n-1]
            for (int j = 0; j < n; j++)
            {
       
                // Check if jth interval lies
                // outside the ith interval
                if (v[i].Item2 < v[j].Item1
                    || v[i].Item1 > v[j].Item2)
                {
                    c--;
                }
            }
       
            // Update the overall maximum
            maxi = Math.Max(c, maxi);
        }
       
        // Print the answer
        Console.Write(maxi);
    }
 
  // Driver code
  static void Main()
  {
    List<Tuple<int, int>> arr = new List<Tuple<int, int>>();
    arr.Add(new Tuple<int,int>(1,2));
    arr.Add(new Tuple<int,int>(3,4));
    arr.Add(new Tuple<int,int>(2,5));
    int N = arr.Count;
   
    // Function Call
    findMaxIntervals(arr, N);
  }
}
 
// This code is contributed by divyesh072019.


Output: 

3

 

Time Complexity: O(N2)
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized by instead of counting the number of intersections, count the number of intervals that do not intersect. The intervals that do not intersect with a particular interval can be divided into two disjoint categories: intervals that fall completely to the left or completely to the right. Using this idea, follow the steps below to solve the problem:

  • Create a hashmap, say M, to map the number of intervals that do not intersect with each interval.
  • Sort the intervals on the basis of their starting point.
  • Traverse the intervals using the variable i
    • Initialize ans as -1 to store the index of the first interval lying completely to the right of ith interval.
    • Initialize low and high as (i + 1) and (N – 1) and perform a binary search as below:
      • Find the value of mid as (low + high)/2.
      • If the starting position of interval[mid] is greater than the ending position of interval[i], store the current index mid in ans and then check in the left half by updating high to (mid – 1).
      • Else check in the right half by updating low to (mid + 1).
    • If the value of ans is not -1, add (N – ans) to M[interval[i]].
  • Now, sort the intervals on the basis of their ending point.
  • Again, traverse the intervals using the variable i and apply a similar approach as above to find the intervals lying completely to the left of the ith interval.
  • After the loop, traverse the map M and store the minimum value in min.
  • Print the value of (N – min) as the result.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Comparator function to sort in
// increasing order of second
// values in each pair
bool compare(pair<int, int> f,
             pair<int, int> s)
{
    return f.second < s.second;
}
 
// Function to hash a pair
struct hash_pair {
    template <class T1, class T2>
    size_t operator()(
        const pair<T1, T2>& p) const
    {
        auto hash1 = hash<T1>{}(p.first);
        auto hash2 = hash<T2>{}(p.second);
        return hash1 ^ hash2;
    }
};
 
// Function to count maximum number
// of intervals that an interval
// can intersect
void findMaxIntervals(
    vector<pair<int, int> > v, int n)
{
 
    // Create a hashmap
    unordered_map<pair<int, int>,
                  int,
                  hash_pair>
        um;
 
    // Sort by starting position
    sort(v.begin(), v.end());
 
    // Traverse all the intervals
    for (int i = 0; i < n; i++) {
 
        // Initalize um[v[i]] as 0
        um[v[i]] = 0;
 
        // Store the starting and
        // ending point of the
        // ith interval
        int start = v[i].first;
        int end = v[i].second;
 
        // Set low and high
        int low = i + 1;
        int high = n - 1;
 
        // Store the required number
        // of intervals
        int ans = -1;
 
        // Apply binary search to find
        // the number of intervals
        // completely lying to the
        // right of the ith interval
        while (low <= high) {
 
            // Find the mid
            int mid = low + (high - low) / 2;
 
            // Condition for searching
            // in the first half
            if (v[mid].first > end) {
                ans = mid;
                high = mid - 1;
            }
 
            // Otherwise search in the
            // second half
            else {
                low = mid + 1;
            }
        }
 
        // Increment um[v[i]] by n-ans
        // if ans!=-1
        if (ans != -1)
            um[v[i]] = n - ans;
    }
 
    // Sort by ending position
    sort(v.begin(), v.end(), compare);
 
    // Traverse all the intervals
    for (int i = 0; i < n; i++) {
 
        // Store the starting and
        // ending point of the
        // ith interval
        int start = v[i].first;
        int end = v[i].second;
 
        // Set low and high
        int low = 0;
        int high = i - 1;
 
        // Store the required number
        // of intervals
        int ans = -1;
 
        // Apply binary search to
        // find the number of intervals
        // completely lying to the
        // left of the ith interval
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (v[mid].second < start) {
                ans = mid;
                low = mid + 1;
            }
            else {
                high = mid - 1;
            }
        }
 
        // Increment um[v[i]] by ans+1
        // if ans!=-1
        if (ans != -1)
            um[v[i]] += (ans + 1);
    }
 
    // Store the answer
    int res = 0;
 
    // Traverse the map
    for (auto it = um.begin();
         it != um.end(); it++) {
 
        // Update the overall answer
        res = max(res, n - it->second);
    }
 
    // Print the answer
    cout << res;
}
 
// Driver Code
int main()
{
    vector<pair<int, int> > arr
        = { { 1, 2 },
            { 3, 4 },
            { 2, 5 } };
 
    int N = arr.size();
 
    // Function Call
    findMaxIntervals(arr, N);
 
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG
{
 
  // Pair class to store in the um as a key
  // with hashcode and equals
  static class Pair
  {
 
    int first;
    int second;
    public Pair(int first, int second)
    {
      this.first = first;
      this.second = second;
    }
 
    @Override public int hashCode()
    {
      final int prime = 31;
      int result = 1;
      result = prime * result + first;
      result = prime * result + second;
      return result;
    }
 
    @Override public boolean equals(Object obj)
    {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      Pair other = (Pair)obj;
      if (first != other.first)
        return false;
      if (second != other.second)
        return false;
      return true;
    }
  }
 
  // Function to count maximum number
  // of intervals that an interval
  // can intersect
  static void findMaxIntervals(ArrayList<Pair> v, int n)
  {
 
    // Create a hashmap
    HashMap<Pair, Integer> um = new HashMap<>();
 
    // Sort by starting position
    Collections.sort(v, (x, y) -> x.first - y.first);
 
    // Traverse all the intervals
    for (int i = 0; i < n; i++) {
 
      // Initalize um for v[i] as 0
      um.put(v.get(i), 0);
 
      // Store the starting and
      // ending point of the
      // ith interval
      int start = v.get(i).first;
      int end = v.get(i).second;
 
      // Set low and high
      int low = i + 1;
      int high = n - 1;
 
      // Store the required number
      // of intervals
      int ans = -1;
 
      // Apply binary search to find
      // the number of intervals
      // completely lying to the
      // right of the ith interval
      while (low <= high) {
 
        // Find the mid
        int mid = low + (high - low) / 2;
 
        // Condition for searching
        // in the first half
        if (v.get(mid).first > end) {
          ans = mid;
          high = mid - 1;
        }
 
        // Otherwise search in the
        // second half
        else {
          low = mid + 1;
        }
      }
 
      // Increment um for v[i] by n-ans
      // if ans!=-1
      if (ans != -1)
        um.put(v.get(i), n - ans);
    }
 
    // Sort by ending position
    Collections.sort(v, (x, y) -> x.second - y.second);
 
    // Traverse all the intervals
    for (int i = 0; i < n; i++) {
 
      // Store the starting and
      // ending point of the
      // ith interval
      int start = v.get(i).first;
      int end = v.get(i).second;
 
      // Set low and high
      int low = 0;
      int high = i - 1;
 
      // Store the required number
      // of intervals
      int ans = -1;
 
      // Apply binary search to
      // find the number of intervals
      // completely lying to the
      // left of the ith interval
      while (low <= high) {
        int mid = low + (high - low) / 2;
        if (v.get(mid).second < start) {
          ans = mid;
          low = mid + 1;
        }
        else {
          high = mid - 1;
        }
      }
 
      // Increment um for v[i] by ans+1
      // if ans!=-1
      if (ans != -1)
        um.put(v.get(i),
               um.get(v.get(i)) + (ans + 1));
    }
 
    // Store the answer
    int res = 0;
 
    // Traverse the map
    for (int second : um.values()) {
 
      // Update the overall answer
      res = Math.max(res, n - second);
    }
 
    // Print the answer
    System.out.println(res);
  }
 
  // Driver Code
  public static void main(String[] args)
  {
 
    ArrayList<Pair> arr = new ArrayList<>();
    arr.add(new Pair(1, 2));
    arr.add(new Pair(3, 4));
    arr.add(new Pair(2, 5));
 
    int N = arr.size();
 
    // Function Call
    findMaxIntervals(arr, N);
  }
}
 
// This code is contributed by Kingash.


Output: 

3

 

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.




My Personal Notes arrow_drop_up
Recommended Articles
Page :