Open In App

Maximum number of intersections possible for any of the N given segments

Given an array arr[] consisting of N pairs of type {L, R}, each representing a segment on the X-axis, the task is to find the maximum number of intersections a segment has with other segments.

Examples:



Input: arr[] = {{1, 6}, {5, 5}, {2, 3}}
Output: 2
Explanation:
Below are the count of each segment that overlaps with the other segments:

  1. The first segment [1, 6] intersects with 2 segments [5, 5] and [2, 3].
  2. The second segment [5, 5] intersects with 1 segment [1, 6].
  3. The third segment [2, 3] intersects with 1 segment [1, 6].

Therefore, the maximum number of intersections among all the segment is 2.



Input: arr[][] = {{4, 8}, {3, 6}, {7, 11}, {9, 10}}
Output: 2

Naive Approach: The simplest approach to solve the given problem is to iterate over all segments and for each segment count the number of intersections by checking it with all other segments and then print the maximum among all the count of intersections obtained.

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

Efficient Approach 1: The above approach can also be optimized based on the following observations:

Follow the steps below to solve the problem:

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum number
// of intersections one segment has with
// all the other given segments
int maximumIntersections(int arr[][2],
                         int N)
{
    // Stores the resultant maximum count
    int count = 0;
 
    // Stores the starting and the
    // ending points
    int L[N], R[N];
 
    for (int i = 0; i < N; i++) {
        L[i] = arr[i][0];
        R[i] = arr[i][1];
    }
 
    // Sort arrays points in the
    // ascending order
    sort(L, L + N);
    sort(R, R + N);
 
    // Traverse the array arr[]
    for (int i = 0; i < N; i++) {
        int l = arr[i][0];
        int r = arr[i][1];
 
        // Find the count of segments
        // on left of ith segment
        int x = lower_bound(R, R + N, l) - R;
 
        // Find the count of segments
        // on right of ith segment
        int y = N - (upper_bound(L, L + N, r) - L);
 
        // Find the total segments not
        // intersecting with the current
        // segment
        int cnt = x + y;
 
        // Store the count of segments
        // that intersect with the
        // ith segment
        cnt = N - cnt - 1;
 
        // Update the value of count
        count = max(count, cnt);
    }
 
    // Return  the resultant count
    return count;
}
 
// Driver Code
int main()
{
    int arr[][2] = { { 1, 6 }, { 5, 5 }, { 2, 3 } };
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << maximumIntersections(arr, N);
 
    return 0;
}




// java program for the above approach
import java.util.*;
 
class GFG
{static int lower_bound(int[] a, int low, int high, long element)
    {
        while(low < high)
        {
            int middle = low + (high - low) / 2;
            if(element > a[middle])
                low = middle + 1;
            else
                high = middle;
        }
        return low;
    }
static int maximumIntersections(int [][]arr,
                         int N)
{
    // Stores the resultant maximum count
    int count = 0;
   
    // Stores the starting and the
    // ending points
    int[] L = new int[N];
    int[] R = new int[N];
    for (int i = 0; i < N; i++) {
        L[i] = arr[i][0];
        R[i] = arr[i][1];
    }
   
    // Sort arrays points in the
    // ascending order
    Arrays.sort(L);
    Arrays.sort(R);
   
    // Traverse the array arr[]
    for (int i = 0; i < N; i++) {
        int l = arr[i][0];
        int r = arr[i][1];
   
        // Find the count of segments
        // on left of ith segment
        int x = lower_bound(L, 0,N, l);
   
        // Find the count of segments
        // on right of ith segment
        int y = N-lower_bound(R, 0,N, r+1);
   
        // Find the total segments not
        // intersecting with the current
        // segment
        int cnt = x + y;
       
        // Store the count of segments
        // that intersect with the
        // ith segment
        cnt = N - cnt - 1;
   
        // Update the value of count
        count = Math.max(count, cnt);
    }
   
    // Return  the resultant count
    return count;
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[][] = { { 1, 6 }, { 5, 5 }, { 2, 3 } };
    int N = arr.length;
    System.out.println(maximumIntersections(arr, N));
}
}
 
// This code is contributed by stream_cipher.




# Python 3 program for the above approach
from bisect import bisect_left, bisect_right
 
 
def lower_bound(a, low, high, element):
 
    while(low < high):
 
        middle = low + (high - low) // 2
        if(element > a[middle]):
            low = middle + 1
        else:
            high = middle
 
    return low
 
 
# Function to find the maximum number
# of intersections one segment has with
# all the other given segments
def maximumIntersections(arr,
                         N):
 
    # Stores the resultant maximum count
    count = 0
 
    # Stores the starting and the
    # ending points
    L = [0]*N
    R = [0]*N
 
    for i in range(N):
        L[i] = arr[i][0]
        R[i] = arr[i][1]
 
    # Sort arrays points in the
    # ascending order
    L.sort()
    R.sort()
 
    # Traverse the array arr[]
    for i in range(N):
        l = arr[i][0]
        r = arr[i][1]
 
        # Find the count of segments
        # on left of ith segment
        x = lower_bound(L, 0, N, l)
 
        # Find the count of segments
        # on right of ith segment
        y = N-lower_bound(R, 0, N, r+1)
 
        # Find the total segments not
        # intersecting with the current
        # segment
        cnt = x + y
 
        # Store the count of segments
        # that intersect with the
        # ith segment
        cnt = N - cnt - 1
 
        # Update the value of count
        count = max(count, cnt)
 
    # Return  the resultant count
    return count
 
# Driver Code
if __name__ == "__main__":
 
    arr = [[1, 6], [5, 5], [2, 3]]
    N = len(arr)
    print(maximumIntersections(arr, N))
 
    # This code is contributed by ukasp.




// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
static int lower_bound(int[] a, int low,
                       int high, long element)
{
    while(low < high)
    {
        int middle = low + (high - low) / 2;
         
        if (element > a[middle])
            low = middle + 1;
        else
            high = middle;
    }
    return low;
}
 
static int maximumIntersections(int [,]arr,
                                int N)
{
     
    // Stores the resultant maximum count
    int count = 0;
   
    // Stores the starting and the
    // ending points
    int[] L = new int[N];
    int[] R = new int[N];
    for(int i = 0; i < N; i++)
    {
        L[i] = arr[i, 0];
        R[i] = arr[i, 1];
    }
   
    // Sort arrays points in the
    // ascending order
    Array.Sort(L);
    Array.Sort(R);
   
    // Traverse the array arr[]
    for(int i = 0; i < N; i++)
    {
        int l = arr[i, 0];
        int r = arr[i, 1];
   
        // Find the count of segments
        // on left of ith segment
        int x = lower_bound(L, 0, N, l);
   
        // Find the count of segments
        // on right of ith segment
        int y = N-lower_bound(R, 0, N, r + 1);
   
        // Find the total segments not
        // intersecting with the current
        // segment
        int cnt = x + y;
       
        // Store the count of segments
        // that intersect with the
        // ith segment
        cnt = N - cnt - 1;
   
        // Update the value of count
        count = Math.Max(count, cnt);
    }
     
    // Return the resultant count
    return count;
}
 
// Driver Code
public static void Main()
{
    int [,]arr = new int[3, 2]{ { 1, 6 },
                                { 5, 5 },
                                { 2, 3 } };
    int N = 3;
     
    Console.Write(maximumIntersections(arr, N));
}
}
 
// This code is contributed by SURENDRA_GANGWAR




<script>
 
// Javascript program for the above approach
function lower_bound(a, low, high, element)
{
    while(low < high)
    {
        let middle = low + Math.floor(
            (high - low) / 2);
             
        if (element > a[middle])
            low = middle + 1;
        else
            high = middle;
    }
    return low;
}
 
// Function to find the maximum number
// of intersections one segment has with
// all the other given segments
function maximumLetersections(arr, N)
{
     
    // Stores the resultant maximum count
    let count = 0;
    
    // Stores the starting and the
    // ending points
    let L = Array.from({length: N}, (_, i) => 0);
    let R = Array.from({length: N}, (_, i) => 0);
    for(let i = 0; i < N; i++)
    {
        L[i] = arr[i][0];
        R[i] = arr[i][1];
    }
    
    // Sort arrays points in the
    // ascending order
    L.sort();
    R.sort();
    
    // Traverse the array arr[]
    for(let i = 0; i < N; i++)
    {
        let l = arr[i][0];
        let r = arr[i][1];
    
        // Find the count of segments
        // on left of ith segment
        let x = lower_bound(L, 0, N, l);
    
        // Find the count of segments
        // on right of ith segment
        let y = N-lower_bound(R, 0, N, r + 1);
    
        // Find the total segments not
        // intersecting with the current
        // segment
        let cnt = x + y;
        
        // Store the count of segments
        // that intersect with the
        // ith segment
        cnt = N - cnt - 1;
    
        // Update the value of count
        count = Math.max(count, cnt);
    }
    
    // Return the resultant count
    return count;
}
 
// Driver Code
let arr = [ [ 1, 6 ], [ 5, 5 ], [ 2, 3 ] ];
let N = arr.length;
 
document.write(maximumLetersections(arr, N));
 
// This code is contributed by susmitakundugoaldanga
 
</script>

Output
2












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

Efficient Approach 2:  Using hashmap.

Intuition: First we define a haspmap. Then traverse over the array and increment the count of L and decrement the count of (R+1) in the map( because we can draw vertical line through all the points within the range of L and R (both including) so we decrement the count of (R+1) point).  At any point in time, the sum of values (total  sum from start till point) in the map will give us the number of overlapping present at the point. We can then find the maximum of this sum, which will give us the maximum number of overlapping possible.

Follow the steps below to solve the problem:

  1. define a haspmap .
  2. Traverse over the array and increment the count of L and decrement the count of (R+1) int the map.
  3. Iterate over the map and keep track of the maximum sum seen so far. This maximum sum will give us the maximum number of the overlapping present.
  4. return the maximum sum.

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the maximum number
// of intersections one segment has with
// all the other given segments
int maximumIntersections(int arr[][2],
                        int N)
{
    // Stores the resultant maximum count
    int count = 0;
 
    // create a map
    map<int , int> pointCount;
     
// traverse the array
    for(int i=0; i<N; i++){
     
    // increment the count of L
    pointCount[arr[i][0]]++;
     
    // decrement the count of (R+1)
    pointCount[arr[i][1] + 1]--;
     
    }
    // store the current sum
    int currSum=0;
    for( auto it : pointCount){
     
    currSum += it.second;
     
    // taking the max of sum
    count= max(count, currSum);
     
    }
     
    // Return the resultant count
    return count;
}
 
// Driver Code
int main()
{
    int arr[][2] = { { 1, 6 }, { 5, 5 }, { 2, 3 } };
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << maximumIntersections(arr, N);
 
    return 0;
}




import java.util.*;
 
class GFG {
    // Function to find the maximum number of intersections
   // one segment has with all the other given segments
    public static int maximumIntersections(int[][] arr, int N) {
        // Stores the resultant maximum count
        int count = 0;
 
        // Create a TreeMap
        TreeMap<Integer, Integer> pointCount = new TreeMap<>();
 
        // Traverse the array
        for (int i = 0; i < N; i++) {
            // Increment the count of L
            pointCount.put(arr[i][0], pointCount.getOrDefault(arr[i][0], 0) + 1);
 
            // Decrement the count of (R+1)
            pointCount.put(arr[i][1] + 1, pointCount.getOrDefault(arr[i][1] + 1, 0) - 1);
        }
 
        // Store the current sum
        int currSum = 0;
        for (int value : pointCount.values()) {
            currSum += value;
 
            // Taking the max of sum
            count = Math.max(count, currSum);
        }
 
        // Return the resultant count
        return count;
    }
 
    // Driver Code
    public static void main(String[] args) {
        int[][] arr = {{1, 6}, {5, 5}, {2, 3}};
        int N = arr.length;
        System.out.println(maximumIntersections(arr, N));
    }
}




def maximumIntersections(arr, N):
    count = 0
    pointCount = {}  # Create a dictionary to store point counts
     
    # Traverse the array of segments
    for i in range(N):
        # Increment the count of the left endpoint of the segment
        pointCount[arr[i][0]] = pointCount.get(arr[i][0], 0) + 1
         
        # Decrement the count of the right endpoint of the segment + 1
        pointCount[arr[i][1] + 1] = pointCount.get(arr[i][1] + 1, 0) - 1
     
    currSum = 0
    # Iterate through the sorted points and their counts
    for point, val in sorted(pointCount.items()):
        currSum += val
        count = max(count, currSum)  # Update the maximum intersection count
     
    return count
 
# Driver Code
if __name__ == "__main__":
    arr = [[1, 6], [5, 5], [2, 3]]
    N = len(arr)
    result = maximumIntersections(arr, N)
    print(result)




using System;
using System.Collections.Generic;
 
class GFG
{
    // Function to find the maximum number of intersections
    // one segment has with all the other given segments
    public static int MaximumIntersections(int[][] arr, int N)
    {
        // Stores the resultant maximum count
        int count = 0;
 
        // Create a SortedDictionary
        SortedDictionary<int, int> pointCount = new SortedDictionary<int, int>();
 
        // Traverse the array
        for (int i = 0; i < N; i++)
        {
            // Increment the count of L
            if (!pointCount.ContainsKey(arr[i][0]))
                pointCount[arr[i][0]] = 1;
            else
                pointCount[arr[i][0]]++;
 
            // Decrement the count of (R+1)
            if (!pointCount.ContainsKey(arr[i][1] + 1))
                pointCount[arr[i][1] + 1] = -1;
            else
                pointCount[arr[i][1] + 1]--;
        }
 
        // Store the current sum
        int currSum = 0;
        foreach (var value in pointCount.Values)
        {
            currSum += value;
 
            // Taking the max of sum
            count = Math.Max(count, currSum);
        }
 
        // Return the resultant count
        return count;
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        int[][] arr = { new int[] { 1, 6 }, new int[] { 5, 5 }, new int[] { 2, 3 } };
        int N = arr.Length;
        Console.WriteLine(MaximumIntersections(arr, N));
    }
}




function MaximumIntersections(arr) {
  // Create an array to store point counts
  let pointCount = [];
 
  // Traverse the array
  for (let i = 0; i < arr.length; i++) {
    // Increment the count of L
    if (!pointCount[arr[i][0]]) {
      pointCount[arr[i][0]] = 1;
    } else {
      pointCount[arr[i][0]]++;
    }
 
    // Decrement the count of (R+1)
    if (!pointCount[arr[i][1] + 1]) {
      pointCount[arr[i][1] + 1] = -1;
    } else {
      pointCount[arr[i][1] + 1]--;
    }
  }
 
  // Store the current sum
  let currSum = 0;
  let count = 0;
  for (let i = 0; i < pointCount.length; i++) {
    if (pointCount[i] !== undefined) {
      currSum += pointCount[i];
 
      // Taking the max of sum
      count = Math.max(count, currSum);
    }
  }
 
  // Return the resultant count
  return count;
}
 
// Driver Code
const arr = [[1, 6], [5, 5], [2, 3]];
console.log(MaximumIntersections(arr)); // Output: 2

Output
2












Time Complexity: O(N*log N) ( insertion in a map takes (log N) and total N number of points)
Auxiliary Space: O(N) (size of map)

Approach 3: Sweep Line Algorithm

Idea: Sort the segments by their left endpoint and then process them on by on using sweep line that moves from left
to right. Then maintain a set of segments that intersect with the sweep line, and update the maximum number of
intersections at each step.

Follow the steps below to solve the problem:

Below is the implementation of the above approach:




#include <bits/stdc++.h>
using namespace std;
 
// Comparison function for sorting events
bool cmp(pair<int, int>& a, pair<int, int>& b)
{
    return a.first < b.first;
}
 
// Function to find the maximum number of intersections
int maxIntersections(vector<pair<int, int> >& segments)
{
    int n = segments.size();
 
    vector<pair<int, int> > events;
    for (int i = 0; i < n; i++) {
        events.push_back({ segments[i].first, 1 });
        events.push_back({ segments[i].second, -1 });
    }
 
    // Sort the events
    sort(events.begin(), events.end(), cmp);
 
    // Traverse the events and keep track of the maximum
    // number of intersections
    int ans = 0, cnt = 0;
    for (int i = 0; i < 2 * n; i++) {
        cnt += events[i].second;
        ans = max(ans, cnt);
    }
    // Return the maximum number of intersections
    return ans;
}
 
int main()
{
    vector<pair<int, int> > segments
        = { { 1, 6 }, { 5, 5 }, { 2, 3 } };
    cout << maxIntersections(segments) << endl;
 
    return 0;
}




import java.util.*;
import java.util.AbstractMap.SimpleEntry;
 
// Comparison function for sorting events
class EventComparator implements Comparator<AbstractMap.SimpleEntry<Integer, Integer>> {
    @Override
    public int compare(AbstractMap.SimpleEntry<Integer, Integer> a, AbstractMap.SimpleEntry<Integer, Integer> b) {
        return Integer.compare(a.getKey(), b.getKey());
    }
}
 
public class MaximumIntersections {
 
    // Function to find the maximum number of intersections
    public static int maxIntersections(List<AbstractMap.SimpleEntry<Integer, Integer>> segments) {
        int n = segments.size();
 
        List<AbstractMap.SimpleEntry<Integer, Integer>> events = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            events.add(new AbstractMap.SimpleEntry<>(segments.get(i).getKey(), 1));
            events.add(new AbstractMap.SimpleEntry<>(segments.get(i).getValue(), -1));
        }
 
        // Sort the events
        Collections.sort(events, new EventComparator());
 
        // Traverse the events and keep track of the maximum
        // number of intersections
        int ans = 0, cnt = 0;
        for (int i = 0; i < 2 * n; i++) {
            cnt += events.get(i).getValue();
            ans = Math.max(ans, cnt);
        }
        // Return the maximum number of intersections
        return ans;
    }
 
    public static void main(String[] args) {
        List<AbstractMap.SimpleEntry<Integer, Integer>> segments = new ArrayList<>();
        segments.add(new AbstractMap.SimpleEntry<>(1, 6));
        segments.add(new AbstractMap.SimpleEntry<>(5, 5));
        segments.add(new AbstractMap.SimpleEntry<>(2, 3));
 
        int maxIntersect = maxIntersections(segments);
        System.out.println(maxIntersect);
    }
}




# Comparison function for sorting events
def cmp(a, b):
    return a[0] < b[0]
 
# Function to find the maximum number of intersections
 
 
def maxIntersections(segments):
    n = len(segments)
 
    events = []
    for i in range(n):
        events.append((segments[i][0], 1))
        events.append((segments[i][1], -1))
 
    # Sort the events
    events.sort(key=lambda x: x[0])
 
    # Traverse the events and keep track of the maximum number of intersections
    ans = 0
    cnt = 0
    for i in range(2 * n):
        cnt += events[i][1]
        ans = max(ans, cnt)
 
    # Return the maximum number of intersections
    return ans
 
 
segments = [(1, 6), (5, 5), (2, 3)]
print(maxIntersections(segments))




using System;
using System.Collections.Generic;
 
// Comparison function for sorting events
class EventComparator : IComparer<KeyValuePair<int, int>>
{
    public int Compare(KeyValuePair<int, int> a, KeyValuePair<int, int> b)
    {
        return a.Key.CompareTo(b.Key);
    }
}
 
public class MaximumIntersections
{
    // Function to find the maximum number of intersections
    public static int MaxIntersections(List<KeyValuePair<int, int>> segments)
    {
        int n = segments.Count;
 
        List<KeyValuePair<int, int>> events = new List<KeyValuePair<int, int>>();
        for (int i = 0; i < n; i++)
        {
            events.Add(new KeyValuePair<int, int>(segments[i].Key, 1));
            events.Add(new KeyValuePair<int, int>(segments[i].Value, -1));
        }
 
        // Sort the events
        events.Sort(new EventComparator());
 
        // Traverse the events and keep track of the maximum
        // number of intersections
        int ans = 0, cnt = 0;
        for (int i = 0; i < 2 * n; i++)
        {
            cnt += events[i].Value;
            ans = Math.Max(ans, cnt);
        }
        // Return the maximum number of intersections
        return ans;
    }
 
    public static void Main(string[] args)
    {
        List<KeyValuePair<int, int>> segments = new List<KeyValuePair<int, int>>();
        segments.Add(new KeyValuePair<int, int>(1, 6));
        segments.Add(new KeyValuePair<int, int>(5, 5));
        segments.Add(new KeyValuePair<int, int>(2, 3));
 
        int maxIntersect = MaxIntersections(segments);
        Console.WriteLine(maxIntersect);
    }
}




function GFG(a, b) {
    return a[0] - b[0];
}
// Function to find the maximum number of the intersections
function maxs(segments) {
    const n = segments.length;
    let events = [];
    for (let i = 0; i < n; i++) {
        events.push([segments[i][0], 1]);
        events.push([segments[i][1], -1]);
    }
    // Sort the events
    events.sort(GFG);
    // Traverse the events and keep track of the maximum number of the intersections
    let ans = 0, cnt = 0;
    for (let i = 0; i < 2 * n; i++) {
        cnt += events[i][1];
        ans = Math.max(ans, cnt);
    }
    // Return the maximum number of the intersections
    return ans;
}
// Test the function with the sample data
const segments = [[1, 6], [5, 5], [2, 3]];
console.log(maxs(segments));

Output:

2

Time Complexity: O(n log n), where n is the number of segments.

Auxiliary Space: O(n log n)


Article Tags :