Maximum number of intersections possible for any of the N given segments
Last Updated :
04 Dec, 2023
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:
- The first segment [1, 6] intersects with 2 segments [5, 5] and [2, 3].
- The second segment [5, 5] intersects with 1 segment [1, 6].
- 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:
- The above approach can be optimized by traversing each segment and calculating the number of segments that do not intersect the current segment using Binary Search and from that find the number of segments that intersect with the current segment
- Suppose [L, R] is the current segment and [P, Q] is another segment then, the segment [L, R] does not intersect with segment [P, Q] if Q < L or P > R.
- Suppose X is the number of the segments not intersecting with segment [L, R] then, the count of segments that intersects segment [L, R] = (N – 1 – X).
Follow the steps below to solve the problem:
- Store all the left points of segments in an array say L[] and all the right points of the segments in the array say R[].
- Sort both the arrays L[] and R[] in ascending order.
- Initialize a variable, say count as 0 to store the count of the maximum intersection a segment has.
- Traverse the array arr[] and perform the following steps:
- Calculate the number of segments left to the current segment {arr[i][0], arr[i][1]} using lower_bound() and store it in a variable say cnt.
- Calculate the number of segments right to the current segment {arr[i][0], arr[i][1]} using upper_bound() and increment the count of cnt by it.
- Update the value of count as the maximum of count and (N – cnt – 1).
- After completing the above steps, print the value of the count as the result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maximumIntersections( int arr[][2],
int N)
{
int count = 0;
int L[N], R[N];
for ( int i = 0; i < N; i++) {
L[i] = arr[i][0];
R[i] = arr[i][1];
}
sort(L, L + N);
sort(R, R + N);
for ( int i = 0; i < N; i++) {
int l = arr[i][0];
int r = arr[i][1];
int x = lower_bound(R, R + N, l) - R;
int y = N - (upper_bound(L, L + N, r) - L);
int cnt = x + y;
cnt = N - cnt - 1;
count = max(count, cnt);
}
return count;
}
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
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)
{
int count = 0 ;
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 ];
}
Arrays.sort(L);
Arrays.sort(R);
for ( int i = 0 ; i < N; i++) {
int l = arr[i][ 0 ];
int r = arr[i][ 1 ];
int x = lower_bound(L, 0 ,N, l);
int y = N-lower_bound(R, 0 ,N, r+ 1 );
int cnt = x + y;
cnt = N - cnt - 1 ;
count = Math.max(count, cnt);
}
return count;
}
public static void main(String[] args)
{
int arr[][] = { { 1 , 6 }, { 5 , 5 }, { 2 , 3 } };
int N = arr.length;
System.out.println(maximumIntersections(arr, N));
}
}
|
Python3
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
def maximumIntersections(arr,
N):
count = 0
L = [ 0 ] * N
R = [ 0 ] * N
for i in range (N):
L[i] = arr[i][ 0 ]
R[i] = arr[i][ 1 ]
L.sort()
R.sort()
for i in range (N):
l = arr[i][ 0 ]
r = arr[i][ 1 ]
x = lower_bound(L, 0 , N, l)
y = N - lower_bound(R, 0 , N, r + 1 )
cnt = x + y
cnt = N - cnt - 1
count = max (count, cnt)
return count
if __name__ = = "__main__" :
arr = [[ 1 , 6 ], [ 5 , 5 ], [ 2 , 3 ]]
N = len (arr)
print (maximumIntersections(arr, N))
|
C#
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)
{
int count = 0;
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];
}
Array.Sort(L);
Array.Sort(R);
for ( int i = 0; i < N; i++)
{
int l = arr[i, 0];
int r = arr[i, 1];
int x = lower_bound(L, 0, N, l);
int y = N-lower_bound(R, 0, N, r + 1);
int cnt = x + y;
cnt = N - cnt - 1;
count = Math.Max(count, cnt);
}
return count;
}
public static void Main()
{
int [,]arr = new int [3, 2]{ { 1, 6 },
{ 5, 5 },
{ 2, 3 } };
int N = 3;
Console.Write(maximumIntersections(arr, N));
}
}
|
Javascript
<script>
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 maximumLetersections(arr, N)
{
let count = 0;
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];
}
L.sort();
R.sort();
for (let i = 0; i < N; i++)
{
let l = arr[i][0];
let r = arr[i][1];
let x = lower_bound(L, 0, N, l);
let y = N-lower_bound(R, 0, N, r + 1);
let cnt = x + y;
cnt = N - cnt - 1;
count = Math.max(count, cnt);
}
return count;
}
let arr = [ [ 1, 6 ], [ 5, 5 ], [ 2, 3 ] ];
let N = arr.length;
document.write(maximumLetersections(arr, N));
</script>
|
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:
- define a haspmap .
- Traverse over the array and increment the count of L and decrement the count of (R+1) int the map.
- 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.
- return the maximum sum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maximumIntersections( int arr[][2],
int N)
{
int count = 0;
map< int , int > pointCount;
for ( int i=0; i<N; i++){
pointCount[arr[i][0]]++;
pointCount[arr[i][1] + 1]--;
}
int currSum=0;
for ( auto it : pointCount){
currSum += it.second;
count= max(count, currSum);
}
return count;
}
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
import java.util.*;
class GFG {
public static int maximumIntersections( int [][] arr, int N) {
int count = 0 ;
TreeMap<Integer, Integer> pointCount = new TreeMap<>();
for ( int i = 0 ; i < N; i++) {
pointCount.put(arr[i][ 0 ], pointCount.getOrDefault(arr[i][ 0 ], 0 ) + 1 );
pointCount.put(arr[i][ 1 ] + 1 , pointCount.getOrDefault(arr[i][ 1 ] + 1 , 0 ) - 1 );
}
int currSum = 0 ;
for ( int value : pointCount.values()) {
currSum += value;
count = Math.max(count, currSum);
}
return count;
}
public static void main(String[] args) {
int [][] arr = {{ 1 , 6 }, { 5 , 5 }, { 2 , 3 }};
int N = arr.length;
System.out.println(maximumIntersections(arr, N));
}
}
|
Python3
def maximumIntersections(arr, N):
count = 0
pointCount = {}
for i in range (N):
pointCount[arr[i][ 0 ]] = pointCount.get(arr[i][ 0 ], 0 ) + 1
pointCount[arr[i][ 1 ] + 1 ] = pointCount.get(arr[i][ 1 ] + 1 , 0 ) - 1
currSum = 0
for point, val in sorted (pointCount.items()):
currSum + = val
count = max (count, currSum)
return count
if __name__ = = "__main__" :
arr = [[ 1 , 6 ], [ 5 , 5 ], [ 2 , 3 ]]
N = len (arr)
result = maximumIntersections(arr, N)
print (result)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public static int MaximumIntersections( int [][] arr, int N)
{
int count = 0;
SortedDictionary< int , int > pointCount = new SortedDictionary< int , int >();
for ( int i = 0; i < N; i++)
{
if (!pointCount.ContainsKey(arr[i][0]))
pointCount[arr[i][0]] = 1;
else
pointCount[arr[i][0]]++;
if (!pointCount.ContainsKey(arr[i][1] + 1))
pointCount[arr[i][1] + 1] = -1;
else
pointCount[arr[i][1] + 1]--;
}
int currSum = 0;
foreach ( var value in pointCount.Values)
{
currSum += value;
count = Math.Max(count, currSum);
}
return count;
}
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));
}
}
|
Javascript
function MaximumIntersections(arr) {
let pointCount = [];
for (let i = 0; i < arr.length; i++) {
if (!pointCount[arr[i][0]]) {
pointCount[arr[i][0]] = 1;
} else {
pointCount[arr[i][0]]++;
}
if (!pointCount[arr[i][1] + 1]) {
pointCount[arr[i][1] + 1] = -1;
} else {
pointCount[arr[i][1] + 1]--;
}
}
let currSum = 0;
let count = 0;
for (let i = 0; i < pointCount.length; i++) {
if (pointCount[i] !== undefined) {
currSum += pointCount[i];
count = Math.max(count, currSum);
}
}
return count;
}
const arr = [[1, 6], [5, 5], [2, 3]];
console.log(MaximumIntersections(arr));
|
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
- This is most efficient approach that can solve the problem in O(N log N) time complexity.
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:
- read the segments from the input and store them in a vector of pair.
- Each pair represents a segment, with the first element being the left endpoint and the second element being the right endpoint.
- create two events (one for the left and one for the right endpoint).
- each event is respresnted as pair of form {x coordinates, +1 or -1}, where +1 or -1 indicates the event is left or right endpoint of the segment.
- store all the events in a single vector.
- Traverse the events : initialize a count of the segment intersecting the sweep line to 0, and initialize a variable to keep track of the maximum no. of intersections seen so far.
- loop through all the events in the sorted order, and for every event:
1. if event is a left event, then increment count.
2. if the event is right event, decrement the count.
3. update the maximum no. of intersections seen so far by taking maximum current count and maximum so far.
- Return the maximum number of intersections.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool cmp(pair< int , int >& a, pair< int , int >& b)
{
return a.first < b.first;
}
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(events.begin(), events.end(), cmp);
int ans = 0, cnt = 0;
for ( int i = 0; i < 2 * n; i++) {
cnt += events[i].second;
ans = max(ans, cnt);
}
return ans;
}
int main()
{
vector<pair< int , int > > segments
= { { 1, 6 }, { 5, 5 }, { 2, 3 } };
cout << maxIntersections(segments) << endl;
return 0;
}
|
Java
import java.util.*;
import java.util.AbstractMap.SimpleEntry;
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 {
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 ));
}
Collections.sort(events, new EventComparator());
int ans = 0 , cnt = 0 ;
for ( int i = 0 ; i < 2 * n; i++) {
cnt += events.get(i).getValue();
ans = Math.max(ans, cnt);
}
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);
}
}
|
Python
def cmp (a, b):
return a[ 0 ] < b[ 0 ]
def maxIntersections(segments):
n = len (segments)
events = []
for i in range (n):
events.append((segments[i][ 0 ], 1 ))
events.append((segments[i][ 1 ], - 1 ))
events.sort(key = lambda x: x[ 0 ])
ans = 0
cnt = 0
for i in range ( 2 * n):
cnt + = events[i][ 1 ]
ans = max (ans, cnt)
return ans
segments = [( 1 , 6 ), ( 5 , 5 ), ( 2 , 3 )]
print (maxIntersections(segments))
|
C#
using System;
using System.Collections.Generic;
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
{
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));
}
events.Sort( new EventComparator());
int ans = 0, cnt = 0;
for ( int i = 0; i < 2 * n; i++)
{
cnt += events[i].Value;
ans = Math.Max(ans, cnt);
}
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);
}
}
|
Javascript
function GFG(a, b) {
return a[0] - b[0];
}
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]);
}
events.sort(GFG);
let ans = 0, cnt = 0;
for (let i = 0; i < 2 * n; i++) {
cnt += events[i][1];
ans = Math.max(ans, cnt);
}
return ans;
}
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)
Similar Reads
Count of intersections of M line segments with N vertical lines in XY plane
Given x coordinates of N vertical lines (parallel to Y-axis) and M line segments extending from (x1, y1) to (x2, y2), the task is to find the total number of intersections of the line segments with the vertical lines. Examples: Input: N = 2, M = 1, lines[] = {-1, 1}, Segments[][4] = {0, 1, 2, 1} Out
15+ min read
Find number of segments covering each point in an given array
Given segments and some points, for each point find the number of segments covering that point. A segment (l, r) covers a point x if and only if l < = x < = r. Examples: Input: Segments = {{0, 3}, {1, 3}, {3, 8}}, Points = {-1, 3, 8}.Output : {0, 3, 1}Explanation : No segments passing through
7 min read
Maximum number of uncrossed lines between two given arrays
Given two arrays A[] and B[], the task is to find the maximum number of uncrossed lines between the elements of the two given arrays. A straight line can be drawn between two array elements A[i] and B[j] only if: A[i] = B[j]The line does not intersect any other line.Examples: Input: A[] = {3, 9, 2},
15+ min read
Count number of pairs of lines intersecting at a Point
Given N lines are in the form a*x + b*y = c (a>0 or a==0 & b>0). Find the number of pairs of lines intersecting at a point. Examples: Input: N=5 x + y = 2 x + y = 4 x = 1 x - y = 2 y = 3 Output: 9 Input: N=2 x + 2y = 2 x + 2y = 4 Output: 0 Approach: Parallel lines never intersect so a meth
7 min read
Maximum number of region in which N non-parallel lines can divide a plane
Given N', the number of non-parallel lines. The task is to find the maximum number of regions in which these lines can divide a plane.Examples: Input : N = 3 Output : 7Input : N = 2 Output : 4 Approach: The above image shows the maximum number of regions a line can divide a plane. One line can divid
4 min read
Maximum number on 7-segment display using N segments : Recursive
Given an integer N, the task is to find the largest number that can be shown with the help of N segments using any number of 7 segment displays.Examples: Input: N = 4 Output: 11 Explanation: Largest number that can be displayed with the help of 4 segments using 2 seven segment displays turned is 11.
6 min read
Number of triangles formed by joining vertices of n-sided polygon with one side common
Given N-sided polygon we need to find the number of triangles formed by joining the vertices of the given polygon with exactly one side being common.Examples: Input : 6 Output : 12 The image below is of a triangle forming inside a Hexagon by joining vertices as shown above. The two triangles formed
4 min read
Maximum path sum in the given arrays with at most K jumps
Given three arrays A, B, and C each having N elements, the task is to find the maximum sum that can be obtained along any valid path with at most K jumps.A path is valid if it follows the following properties: It starts from the 0th index of an array.It ends at (N-1)th index of an array.For any elem
15+ min read
Find minimum y coordinates from set of N lines in a plane
Given N lines in a plane in the form of a 2D array arr[][] such that each row consists of 2 integers(say m & c) where m is the slope of the line and c is the y-intercept of that line. You are given Q queries each consist of x-coordinates. The task is to find the minimum possible y-coordinate cor
15+ min read
Maximum ranges that can be uniquely represented by any integer from the range
Given an array arr[] consisting of N ranges of the form {L, R}, the task is to find the maximize the number of ranges such that each range can be uniquely represented by any integer from that range. Examples: Input: arr[] = {{1, 2}, {2, 3}, {3, 4}}Output: 3Explanation:Number of ranges can be maximiz
8 min read