Given an array of positive integers(may contain duplicates) and a number ‘m’, find the number of unordered triplets ((Ai, Aj, Ak) and (Aj, Ai, Ak) and other permutations are counted as one only) with product equal to ‘m’.
Examples:
Input: arr[] = { 1, 4, 6, 2, 3, 8}, M = 24
Output: 3
The triplets are {1, 4, 6} {1, 3, 8} {4, 2, 3}Input: arr[] = { 0, 4, 6, 2, 3, 8}, M = 18
Output: 0
There are no triplets in this case
A solution with O(N2) has been discussed in the previous post. In this post a better approach with lesser complexity has been discussed.
Approach: The below algorithm is followed to solve the above problem.
- Use a hash-map to count the frequency of every element in the given array.
- Declare a set which can store triplets, so that only unordered triplets are taken to count.
- Iterate from 1 to sqrt(m) in a loop(let variable be i), since the maximum number by which M is divisible is sqrt(M) leaving out M.
- Check if M is divisible by i or not and i is present in the array of integers or not, if it is, then again loop from 1 to M/i.(let the loop variable be j).
- Again Check if M is divisible by j or not and j is present in the array of integers or not, if it is then check if the remaining number that is ( (M / i) / j) is present or not.
- If it is present, then a triplet has been formed. To avoid duplicate triplets, insert them in the set in sorted order.
- Check if the set the size increases after the insertion of triplet if it does then use combinatorics to find the number of triplets.
- To find the number of triplets, the following conditions will be there.
- If all of the Ai, Aj and Ak are unique, then number of combinations will be the product of their frequencies.
- If all of them are same, then we can only choose three of them, hence the formula stands at
. - If any of the two are same(let Ai and Aj), the count will be
* frequency[Ak]
Below is the implementation of the above approach.
// C++ program to find the // number of triplets in array // whose product is equal to M #include <bits/stdc++.h> using namespace std;
// Function to count the triplets int countTriplets( int a[], int m, int n)
{ // hash-map to store the frequency of every number
unordered_map< int , int > frequency;
// set to store the unique triplets
set<pair< int , pair< int , int > > > st;
// count the number of times
// every element appears in a map
for ( int i = 0; i < n; i++) {
frequency[a[i]] += 1;
}
// stores the answer
int ans = 0;
// iterate till sqrt(m) since tnum2t is the
// maximum number tnum2t can divide M except itself
for ( int i = 1; i * i <= m; i++) {
// if divisible and present
if (m % i == 0 and frequency[i]) {
// remaining number after division
int num1 = m / i;
// iterate for the second number of the triplet
for ( int j = 1; j * j <= num1; j++) {
// if divisible and present
if (num1 % j == 0 and frequency[j]) {
// remaining number after division
int num2 = num1 / j;
// if the third number is present in array
if (frequency[num2]) {
// a temp array to store the triplet
int temp[] = { num2, i, j };
// sort the triplets
sort(temp, temp + 3);
// get the size of set
int setsize = st.size();
// insert the triplet in ascending order
st.insert({ temp[0], { temp[1], temp[2] } });
// if the set size increases after insertion,
// it means a new triplet is found
if (setsize != st.size()) {
// if all the number in triplets are unique
if (i != j and j != num2)
ans += frequency[i] * frequency[j] * frequency[num2];
// if Ai and Aj are same among triplets
else if (i == j && j != num2)
ans += (frequency[i] * (frequency[i] - 1) / 2)
* frequency[num2];
// if Aj and Ak are same among triplets
else if (j == num2 && j != i)
ans += (frequency[j] * (frequency[j] - 1) / 2)
* frequency[i];
// if three of them are
// same among triplets
else if (i == j and j == num2)
ans += (frequency[i] * (frequency[i] - 1) * (frequency[i] - 2) / 6);
// if Ai and Ak are same among triplets
else
ans += (frequency[i] * (frequency[i] - 1) / 2)
* frequency[j];
}
}
}
}
}
}
return ans;
} // Driver Code int main()
{ int a[] = { 1, 4, 6, 2, 3, 8 };
int m = 24;
int n = sizeof (a) / sizeof (a[0]);
cout << countTriplets(a, m, n);
return 0;
} |
// Java program to find the // number of triplets in array // whose product is equal to M import java.util.*;
class GFG
{ // Function to count the triplets static int countTriplets( int a[], int m, int n)
{ // hash-map to store
// the frequency of every number
HashMap<Integer, Integer> frequency
= new HashMap<>();
// put to store the unique triplets
Set<String> st = new HashSet<String>();
// count the number of times
// every element appears in a map
for ( int i = 0 ; i < n; i++)
{
frequency.put(a[i],(frequency.get(a[i]) ==
null ? 1 :(frequency.get(a[i]) + 1 )));
}
// stores the answer
int ans = 0 ;
// iterate till sqrt(m) since tnum2t is the
// maximum number tnum2t can divide M except itself
for ( int i = 1 ; i * i <= m; i++)
{
// if divisible && present
if (m % i == 0 && frequency.get(i)!= null )
{
// remaining number after division
int num1 = m / i;
// iterate for the second number of the triplet
for ( int j = 1 ; j * j <= num1; j++)
{
// if divisible && present
if (num1 % j == 0 && frequency.get(j) != null )
{
// remaining number after division
int num2 = num1 / j;
// if the third number is present in array
if (frequency.get(num2) != null )
{
// a temp array to store the triplet
int temp[] = { num2, i, j };
// sort the triplets
Arrays.sort(temp);
// get the size of put
int setsize = st.size();
// add the triplet in ascending order
st.add(temp[ 0 ]+ " " + temp[ 1 ]+ " " +temp[ 2 ] );
// if the put size increases after addition,
// it means a new triplet is found
if (setsize != st.size())
{
// if all the number in triplets are unique
if (i != j && j != num2)
ans += frequency.get(i) *
frequency.get(j) *
frequency.get(num2);
// if Ai && Aj are same among triplets
else if (i == j && j != num2)
ans += (frequency.get(i) *
(frequency.get(i) - 1 ) / 2 )
* frequency.get(num2);
// if Aj && Ak are same among triplets
else if (j == num2 && j != i)
ans += (frequency.get(j) *
(frequency.get(j) - 1 ) / 2 )
* frequency.get(i);
// if three of them are
// same among triplets
else if (i == j && j == num2)
ans += (frequency.get(i) *
(frequency.get(i) - 1 ) *
(frequency.get(i) - 2 ) / 6 );
// if Ai && Ak are same among triplets
else
ans += (frequency.get(i) *
(frequency.get(i) - 1 ) / 2 )
* frequency.get(j);
}
}
}
}
}
}
return ans;
} // Driver Code public static void main(String args[])
{ int a[] = { 1 , 4 , 6 , 2 , 3 , 8 };
int m = 24 ;
int n = a.length;
System.out.println(countTriplets(a, m, n));
} } // This code is contributed by Arnab Kundu |
# Python3 program to find the # number of triplets in array # whose product is equal to M import math
# Function to count the triplets def countTriplets(a, m, n):
# hash-map to store
# the frequency of every number
frequency = {}
# put to store the unique triplets
st = set ({})
# count the number of times
# every element appears in a map
for i in range (n):
if a[i] in frequency:
frequency[a[i]] + = 1
else :
frequency[a[i]] = 1
# stores the answer
ans = 0
# iterate till sqrt(m) since tnum2t is the
# maximum number tnum2t can divide M except itself
i = 1
while i * i < = m:
# if divisible && present
if (m % i = = 0 and i in frequency):
# remaining number after division
num1 = int (m / i)
# iterate for the second number of the triplet
j = 1
while j * j < = num1:
# if divisible && present
if (num1 % j = = 0 and j in frequency):
# remaining number after division
num2 = math.floor(num1 / j)
# if the third number is present in array
if num2 in frequency:
# a temp array to store the triplet
temp = [ num2, i, j ]
# sort the triplets
temp.sort()
# get the size of put
setsize = len (st)
# add the triplet in ascending order
st.add( str (temp[ 0 ]) + " " + str (temp[ 1 ]) + " " + str (temp[ 2 ]))
# if the put size increases after addition,
# it means a new triplet is found
if setsize ! = len (st):
# if all the number in
# triplets are unique
if (i ! = j and j ! = num2):
ans + = frequency[i] * frequency[j] * frequency[num2]
# if Ai && Aj are same among triplets
elif (i = = j and j ! = num2):
ans + = (frequency[i] * (frequency[i] - 1 ) / 2 ) * frequency[num2]
# if Aj && Ak are same among triplets
elif (j = = num2 and j ! = i):
ans + = (frequency[j] * (frequency[j] - 1 ) / 2 ) * frequency[i]
# if three of them are
# same among triplets
elif (i = = j and j = = num2):
ans + = (frequency[i] * (frequency[i] - 1 ) * (frequency[i] - 2 ) / 6 )
# if Ai && Ak are same among triplets
else :
ans + = (frequency[i] * (frequency[i] - 1 ) / 2 ) * frequency[j]
j + = 1
i + = 1
return int (ans)
a = [ 1 , 4 , 6 , 2 , 3 , 8 ]
m = 24 ;
n = len (a)
print (countTriplets(a, m, n))
# This code is contributed by rameshtravel07. |
// C# program to find the // number of triplets in array // whose product is equal to M using System;
using System.Collections.Generic;
class GFG {
// Function to count the triplets
static int countTriplets( int [] a, int m, int n)
{
// hash-map to store
// the frequency of every number
Dictionary< int , int > frequency = new Dictionary< int , int >();
// put to store the unique triplets
HashSet< string > st = new HashSet< string >();
// count the number of times
// every element appears in a map
for ( int i = 0; i < n; i++)
{
if (frequency.ContainsKey(a[i]))
{
frequency[a[i]] += 1;
}
else {
frequency[a[i]] = 1;
}
}
// stores the answer
int ans = 0;
// iterate till sqrt(m) since tnum2t is the
// maximum number tnum2t can divide M except itself
for ( int i = 1; i * i <= m; i++)
{
// if divisible && present
if (m % i == 0 && frequency.ContainsKey(i))
{
// remaining number after division
int num1 = m / i;
// iterate for the second number of the triplet
for ( int j = 1; j * j <= num1; j++)
{
// if divisible && present
if (num1 % j == 0 && frequency.ContainsKey(j))
{
// remaining number after division
int num2 = num1 / j;
// if the third number is present in array
if (frequency.ContainsKey(num2))
{
// a temp array to store the triplet
int [] temp = { num2, i, j };
// sort the triplets
Array.Sort(temp);
// get the size of put
int setsize = st.Count;
// add the triplet in ascending order
st.Add(temp[0].ToString()+ " " + temp[1].ToString()+ " " +temp[2].ToString());
// if the put size increases after addition,
// it means a new triplet is found
if (setsize != st.Count)
{
// if all the number in triplets are unique
if (i != j && j != num2)
ans += frequency[i] *
frequency[j] *
frequency[num2];
// if Ai && Aj are same among triplets
else if (i == j && j != num2)
ans += (frequency[i] *
(frequency[i] - 1) / 2)
* frequency[num2];
// if Aj && Ak are same among triplets
else if (j == num2 && j != i)
ans += (frequency[j] *
(frequency[j] - 1) / 2)
* frequency[i];
// if three of them are
// same among triplets
else if (i == j && j == num2)
ans += (frequency[i] *
(frequency[i] - 1) *
(frequency[i] - 2) / 6);
// if Ai && Ak are same among triplets
else
ans += (frequency[i] *
(frequency[i] - 1) / 2)
* frequency[j];
}
}
}
}
}
}
return ans;
}
// Driver code
static void Main() {
int [] a = { 1, 4, 6, 2, 3, 8 };
int m = 24;
int n = a.Length;
Console.Write(countTriplets(a, m, n));
}
} // This code is contributed by decode2207. |
<script> // JavaScript program to find the // number of triplets in array // whose product is equal to M // Function to count the triplets function countTriplets(a,m,n)
{ // hash-map to store
// the frequency of every number
let frequency = new Map();
// put to store the unique triplets
let st = new Set();
// count the number of times
// every element appears in a map
for (let i = 0; i < n; i++)
{
frequency.set(a[i],(frequency.get(a[i]) ==
null ? 1:(frequency.get(a[i]) + 1)));
}
// stores the answer
let ans = 0;
// iterate till sqrt(m) since tnum2t is the
// maximum number tnum2t can divide M except itself
for (let i = 1; i * i <= m; i++)
{
// if divisible && present
if (m % i == 0 && frequency.get(i)!= null )
{
// remaining number after division
let num1 = m / i;
// iterate for the second number of the triplet
for (let j = 1; j * j <= num1; j++)
{
// if divisible && present
if (num1 % j == 0 && frequency.get(j) != null )
{
// remaining number after division
let num2 = Math.floor(num1 / j);
// if the third number is present in array
if (frequency.get(num2) != null )
{
// a temp array to store the triplet
let temp = [ num2, i, j ];
// sort the triplets
temp.sort( function (a,b){ return a-b;});
// get the size of put
let setsize = st.size;
// add the triplet in ascending order
st.add(temp[0]+ " " + temp[1]+ " " +temp[2] );
// if the put size increases after addition,
// it means a new triplet is found
if (setsize != st.size)
{
// if all the number in
// triplets are unique
if (i != j && j != num2)
ans += frequency.get(i) *
frequency.get(j) *
frequency.get(num2);
// if Ai && Aj are same among triplets
else if (i == j && j != num2)
ans += (frequency.get(i) *
(frequency.get(i) - 1) / 2)
* frequency.get(num2);
// if Aj && Ak are same among triplets
else if (j == num2 && j != i)
ans += (frequency.get(j) *
(frequency.get(j) - 1) / 2)
* frequency.get(i);
// if three of them are
// same among triplets
else if (i == j && j == num2)
ans += (frequency.get(i) *
(frequency.get(i) - 1) *
(frequency.get(i) - 2) / 6);
// if Ai && Ak are same among triplets
else
ans += (frequency.get(i) *
(frequency.get(i) - 1) / 2)
* frequency.get(j);
}
}
}
}
}
}
return ans;
} // Driver Code let a=[1, 4, 6, 2, 3, 8 ]; let m = 24; let n = a.length; document.write(countTriplets(a, m, n)); // This code is contributed by avanitrachhadiya2155 </script> |
Output:
3
Time Complexity: O(N * log N)