Related Articles

# Count of intersecting lines formed from every possible pair of given points

• Difficulty Level : Expert
• Last Updated : 04 Aug, 2021

Given two arrays of integers, X and Y representing points in the X-Y plane. Calculate the number of intersecting pairs of line segments formed from every possible pair of coordinates.

Example:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: X = [0, 1, 0, 1], Y = [0, 1, 3, 2]

Output: 14

Explanation:

For simplicity let’s denote A = [0, 0], B = [1, 1], C = [1, 2], D = [0, 3].

1. Line segment between point (A, B) and point (A, C) intersects.
2. Line segment between point (A, B) and point (A, D) intersects.
3. Line segment between point (A, B) and point (B, D) intersects.
4. Line segment between point (A, B) and point (C, D) intersects.
5. Line segment between point (A, B) and point (B, C) intersects.
6. Line segment between point (A, C) and point (C, D) intersects.
7. Line segment between point (A, C) and point (B, D) intersects
8. Line segment between point (A, C) and point (A, D) intersects.
9. Line segment between point (A, C) and point (B, C) intersects..
10. Line segment between point (A, D) and point (B, D) intersects.
11. Line segment between point (A, D) and point (C, D) intersects.
12. Line segment between point (B, C) and point (B, D) intersects.
13. Line segment between point (B, C) and point (C, D) intersects.
14. Line segment between point (B, D) and point (C, D) intersects.

Input: X = [0, 0, 0, 2], Y = [0, 2, 4, 0]

Output: 6

Naive Approach:

1. Store all pairs of coordinates in a data structure.
2. For each pair of pairs of coordinates check if there are parallel or not. If they are not parallel then this line must intersect. Increase the answer by 1.

Time Complexity: O(N^4)

Efficient Approach:

1. For every pair of coordinates, store these parameters (slope, intercept on the x-axis or y-axis) of a line.
2. For lines parallel to X axis:
•  Slope = 0, Intercept = Y[i]
3. For lines parallel to Y axis:
• Slope = INF, Intercept = X[i]
4. For all other lines:
• Slope = (dy/dx =  (y2 – y1)/(x2 – x1)
• To calculate intercept we know the general form of a line i.e. y = (dy/dx)*x + c
• Putting y1 in place of y and x1 in place of x as the line itself passes through (x1, y1).
• After the above step, we get Intercept = (y1*dx – x1*dy)/dx
5. Then for every line, we have three cases:
• A line can have the same slope and same intercept as some other line. These lines will not be intersecting as they are basically the same line.
• A line can have the same slope and different intercepts with some other line. These lines will also not intersect as they are parallel.
• A line can have a different slope from some other line. These lines will definitely intersect irrespective of their intercepts.
6. Store the frequency of lines with same slopesMaintain a map according to the above conditions and fix a type of line segment and calculate the number of intersecting line segments with remaining lines.

Note:

In the below implementation we have avoided the use of doubles to avoid bugs caused due to precision errors.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach`` ` `#include ``using` `namespace` `std;`` ` `// Function to calculate total pairs``// of intersecting lines``int` `totalPairsOfIntersectineLines(``    ``int` `X[], ``int` `Y[], ``int` `N)``{``    ``// Set to check the occurences``    ``// of slope and intercept``    ``// It will store the slope dy/dx``    ``// as {dy, dx} and intercept as {c1, c2}``    ``set, pair<``int``, ``int``> > > st;`` ` `    ``// Map to keep track of count of slopes``    ``map, ``int``> mp;``    ``for` `(``int` `i = 0; i < N; i++) {``        ``for` `(``int` `j = i + 1; j < N; j++) {`` ` `            ``// Numerator of the slope``            ``int` `dx = X[j] - X[i];`` ` `            ``// Denominator of the slope``            ``int` `dy = Y[j] - Y[i];`` ` `            ``// Making dx and dy coprime``            ``// so that we do not repeat``            ``int` `g = __gcd(dx, dy);``            ``dx /= g, dy /= g;`` ` `            ``// Checking for lines parallel to y axis``            ``if` `(dx == 0) {`` ` `                ``// Intercepts of the line``                ``int` `c1, c2;``                ``c1 = X[i];``                ``c2 = INT_MAX;`` ` `                ``// pair to check the previous occurence of``                ``// the line parameters``                ``pair, pair<``int``, ``int``> > pr``                    ``= { { dx, dy }, { c1, c2 } };`` ` `                ``if` `(st.find(pr) != st.end()) {``                    ``// Do nothing as this line is same just``                    ``// an etenstion to some line with same``                    ``// slope and intercept``                ``}``                ``else` `{`` ` `                    ``// Insert this line to the set``                    ``st.insert(pr);`` ` `                    ``// increase the count of the slope of``                    ``// this line``                    ``mp[pr.first]++;``                ``}``            ``}`` ` `            ``// Checking for lines parallel to x- axis``            ``else` `if` `(dy == 0) {``                ``int` `c1, c2;``                ``c2 = Y[i];``                ``c1 = INT_MAX;``                ``pair, pair<``int``, ``int``> > pr``                    ``= { { dx, dy }, { c1, c2 } };`` ` `                ``if` `(st.find(pr) != st.end()) {``                    ``// Do nothing as this line is same just``                    ``// an etenstion to some line with same``                    ``// slope and intercept``                ``}``                ``else` `{`` ` `                    ``// Insert this line to the set``                    ``st.insert(pr);`` ` `                    ``// increase the count of the slope of``                    ``// this line``                    ``mp[pr.first]++;``                ``}``            ``}``            ``else` `{``                ``int` `c1, c2;`` ` `                ``// c1 = y*dx - dy*dx``                ``// If one of them is negative, then``                ``// generalising that dx is negative and dy``                ``// is positive so that we don't repeat``                ``if` `(dx > 0 && dy < 0) {``                    ``dx *= -1, dy *= -1;``                ``}`` ` `                ``// Calculating the intercepts``                ``c1 = Y[i] * dx - dy * X[i];``                ``c2 = dx;`` ` `                ``// Normalising the intercepts``                ``int` `g2 = __gcd(c1, c2);``                ``c1 /= g2, c2 /= g2;``                ``pair, pair<``int``, ``int``> > pr``                    ``= { { dx, dy }, { c1, c2 } };`` ` `                ``if` `(st.find(pr) != st.end()) {``                    ``// Do nothing as this line is same just``                    ``// an etenstion to some line with same``                    ``// slope and intercept``                ``}``                ``else` `{`` ` `                    ``// Insert this line to the set``                    ``st.insert(pr);`` ` `                    ``// increase the count of the slope of``                    ``// this line``                    ``mp[pr.first]++;``                ``}``            ``}``        ``}``    ``}`` ` `    ``// vector for storing all the counts``    ``// of the lines with different parameters``    ``vector<``int``> v;``    ``for` `(``auto` `count : mp) {``        ``v.push_back(count.second);``    ``}``    ``// Counting all different line segments``    ``int` `cnt = accumulate(v.begin(), v.end(), 0);`` ` `    ``// Variable to store the count``    ``int` `ans = 0;``    ``for` `(``int` `i = 0; i < v.size(); i++) {`` ` `        ``// Decreasing the count by current line segments``        ``// which will be parallel to each other``        ``cnt -= v[i];`` ` `        ``// Intersecting all other line``        ``// segments with this line segment``        ``ans += cnt * v[i];``    ``}``    ``return` `ans;``}`` ` `// Driver Code``int` `main()``{``    ``// Given Input``    ``int` `N = 4;``    ``int` `X[] = { 0, 1, 0, 1 };``    ``int` `Y[] = { 0, 1, 3, 2 };`` ` `    ``// Function call``    ``cout << totalPairsOfIntersectineLines(X, Y, N);``    ``return` `0;``}`
Output
`14`

Time Complexity: O(N*N*logN)

Space Complexity: O(N)

My Personal Notes arrow_drop_up