Given X and Y coordinates of N points on a Cartesian plane. The task is to find the number of possible triangles with the non-zero area that can be formed by joining each point to every other point.
Examples:
Input: P[] = {{0, 0}, {2, 0}, {1, 1}, {2, 2}} Output: 3 Possible triangles can be [(0, 0}, (2, 0), (1, 1)], [(0, 0), (2, 0), (2, 2)] and [(1, 1), (2, 2), (2, 0)] Input : P[] = {{0, 0}, {2, 0}, {1, 1}} Output : 1
A Naive approach has been already discussed in Number of possible Triangles in a Cartesian coordinate system
7Efficient Approach: Consider a point Z and find its slope with every other point. Now, if two points are having the same slope with point Z that means the 3 points are collinear and they cannot form a triangle. Hence, the number of triangles having Z as one of its points is the number of ways of choosing 2 points from the remaining points and then subtracting the number of ways of choosing 2 points from points having the same slope with Z. Since Z can be any point among N points, we have to iterate one more loop.
Steps to solve the problem:
- Initialize an empty map mp and a variable ans to 0.
- Iterate from 0 to N-1.
- Clear the map mp.
- For each point i, calculate the slope of all other points with respect to the current point.
- calculate the greatest common divisor (GCD) of the difference in X and Y coordinate
- between point i and j. Divide the difference in X and Y coordinates by their GCD.
- Store the slope as a key-value pair in the map mp, where the key is a pair of integers representing the slope and the value is the frequency of that slope.
- Calculate the number of ways by the formula (N – (i + 1)) * (N – (i + 1) – 1) / 2. Add this value to the and.
- Iterate over the map mp, and for each key-value pair, calculate the number of ways by the formula j.second * (j.second – 1) /2.
- Subtract this value from the and.
- Return the final value of ans.
Below is the implementation of the above approach:
C++
// C++ implementation of the above approach #include <bits/stdc++.h> using namespace std; // This function returns the required number // of triangles int countTriangles(pair< int , int > P[], int N) { // Hash Map to store the frequency of // slope corresponding to a point (X, Y) map<pair< int , int >, int > mp; int ans = 0; // Iterate over all possible points for ( int i = 0; i < N; i++) { mp.clear(); // Calculate slope of all elements // with current element for ( int j = i + 1; j < N; j++) { int X = P[i].first - P[j].first; int Y = P[i].second - P[j].second; // find the slope with reduced // fraction int g = __gcd(X, Y); X /= g; Y /= g; mp[{ X, Y }]++; } int num = N - (i + 1); // Total number of ways to form a triangle // having one point as current element ans += (num * (num - 1)) / 2; // Subtracting the total number of ways to // form a triangle having the same slope or are // collinear for ( auto j : mp) ans -= (j.second * (j.second - 1)) / 2; } return ans; } // Driver Code to test above function int main() { pair< int , int > P[] = { { 0, 0 }, { 2, 0 }, { 1, 1 }, { 2, 2 } }; int N = sizeof (P) / sizeof (P[0]); cout << countTriangles(P, N) << endl; return 0; } |
Java
// Java implementation of the above approach import java.util.*; class GFG { // A recursive function to find gcd of two numbers. static int __gcd( int x, int y) { x = Math.abs(x); y = Math.abs(y); while (y > 0 ) { int t = y; y = x % y; x = t; } return x; } // This function returns the required number // of triangles static int countTriangles( int [][] P, int N) { // Hash Map to store the frequency of // slope corresponding to a point (X, Y) // map<pair<int, int>, int> mp; HashMap<String, Integer> mp = new HashMap<String, Integer>(); int ans = 0 ; // Iterate over all possible points for ( int i = 0 ; i < N; i++) { mp.clear(); // Calculate slope of all elements // with current element for ( int j = i + 1 ; j < N; j++) { int X = P[i][ 0 ] - P[j][ 0 ]; int Y = P[i][ 1 ] - P[j][ 1 ]; // find the slope with reduced // fraction int g = __gcd(X, Y); X = ( int )(X / g); Y = ( int )(Y / g); String key = String.valueOf(X) + "," + String.valueOf(Y); if (!mp.containsKey(key)) mp.put(key, 0 ); mp.put(key, mp.get(key) + 1 ); } int num = N - (i + 1 ); // Total number of ways to form a triangle // having one point as current element ans += ( int )((num * (num - 1 )) / 2 ); // Subtracting the total number of ways to // form a triangle having the same slope or are // collinear for (Map.Entry<String, Integer> entry : mp.entrySet()) ans -= (entry.getValue() * (entry.getValue() - 1 )) / 2 ; } return ans; } // Driver Code to test above function public static void main(String[] args) { int [][] P = { { 0 , 0 }, { 2 , 0 }, { 1 , 1 }, { 2 , 2 } }; int N = P.length; System.out.println(countTriangles(P, N)); } } // The code is contributed by phasing17 |
Python3
# Python3 implementation of the above approach from collections import defaultdict from math import gcd # This function returns the # required number of triangles def countTriangles(P, N): # Hash Map to store the frequency of # slope corresponding to a point (X, Y) mp = defaultdict( lambda : 0 ) ans = 0 # Iterate over all possible points for i in range ( 0 , N): mp.clear() # Calculate slope of all elements # with current element for j in range (i + 1 , N): X = P[i][ 0 ] - P[j][ 0 ] Y = P[i][ 1 ] - P[j][ 1 ] # find the slope with reduced # fraction g = gcd(X, Y) X / / = g Y / / = g mp[(X, Y)] + = 1 num = N - (i + 1 ) # Total number of ways to form a triangle # having one point as current element ans + = (num * (num - 1 )) / / 2 # Subtracting the total number of # ways to form a triangle having # the same slope or are collinear for j in mp: ans - = (mp[j] * (mp[j] - 1 )) / / 2 return ans # Driver Code if __name__ = = "__main__" : P = [[ 0 , 0 ], [ 2 , 0 ], [ 1 , 1 ], [ 2 , 2 ]] N = len (P) print (countTriangles(P, N)) # This code is contributed by Rituraj Jain |
C#
// C# implementation of the above approach using System; using System.Collections.Generic; class GFG { // A recursive function to find gcd of two numbers. static int __gcd( int x, int y) { x = Math.Abs(x); y = Math.Abs(y); while (y > 0) { int t = y; y = x % y; x = t; } return x; } // This function returns the required number // of triangles static int countTriangles( int [, ] P, int N) { // Hash Map to store the frequency of // slope corresponding to a point (X, Y) // map<pair<int, int>, int> mp; Dictionary< string , int > mp = new Dictionary< string , int >(); int ans = 0; // Iterate over all possible points for ( int i = 0; i < N; i++) { mp.Clear(); // Calculate slope of all elements // with current element for ( int j = i + 1; j < N; j++) { int X = P[i, 0] - P[j, 0]; int Y = P[i, 1] - P[j, 1]; // find the slope with reduced // fraction int g = __gcd(X, Y); X = ( int )(X / g); Y = ( int )(Y / g); int [] l1 = { X, Y }; string key = string .Join( ", " , l1); if (!mp.ContainsKey(key)) mp[key] = 0; mp[key]++; } int num = N - (i + 1); // Total number of ways to form a triangle // having one point as current element ans += ( int )((num * (num - 1)) / 2); // Subtracting the total number of ways to // form a triangle having the same slope or are // collinear foreach ( var entry in mp) ans -= (entry.Value * (entry.Value - 1)) / 2; } return ans; } // Driver Code to test above function public static void Main( string [] args) { int [, ] P = { { 0, 0 }, { 2, 0 }, { 1, 1 }, { 2, 2 } }; int N = P.GetLength(0); Console.WriteLine(countTriangles(P, N)); } } // The code is contributed by Nidhi goel |
Javascript
// JavaScript implementation of the above approach // A recursive function to find gcd of two numbers. function __gcd(x, y) { if (( typeof x !== 'number' ) || ( typeof y !== 'number' )) return false ; x = Math.abs(x); y = Math.abs(y); while (y) { var t = y; y = x % y; x = t; } return x; } // This function returns the required number // of triangles function countTriangles(P, N) { // Hash Map to store the frequency of // slope corresponding to a point (X, Y) // map<pair<int, int>, int> mp; let mp = new Map(); let ans = 0; // Iterate over all possible points for (let i = 0; i < N; i++) { mp.clear(); // Calculate slope of all elements // with current element for (let j = i + 1; j < N; j++) { let X = P[i][0] - P[j][0]; let Y = P[i][1] - P[j][1]; // find the slope with reduced // fraction let g = __gcd(X, Y); X = Math.floor(X/g); Y = Math.floor(Y/g); if (mp.has([X, Y].join())){ mp.set([X, Y].join(), mp.get([X, Y].join()) + 1); } else { mp.set([X, Y].join(), 1); } } let num = N - (i + 1); // Total number of ways to form a triangle // having one point as current element ans += Math.floor((num * (num - 1)) / 2); // Subtracting the total number of ways to // form a triangle having the same slope or are // collinear for (const [key, value] of mp.entries()) ans -= (value * (value - 1)) / 2; } return ans; } // Driver Code to test above function let P = [[0, 0], [2, 0], [1, 1 ], [2, 2 ]]; let N = P.length; console.log(countTriangles(P, N)); // The code is contributed by Nidhi goel |
3
Time Complexity: O(N2logN)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!