给定一个正整数数组(可能包含重复项)和一个数字’m’,找到无序三元组((A i ,A j ,A k )和(A j ,A i ,A k )的数量,其他置换为仅计为1) ,其乘积等于’m’。
例子:
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
在上一篇文章中已经讨论了O(N 2 )的解决方案。在这篇文章中,已经讨论了一种具有较少复杂性的更好方法。
方法:下面的算法可以解决上述问题。
- 使用哈希图计算给定数组中每个元素的频率。
- 声明一个可以存储三元组的集合,这样就只考虑无序三元组。
- 在循环中从1迭代到sqrt(m)(让变量为i),因为可以将M整除的最大数目是sqrt(M),而忽略了M。
- 检查M是否可被i整除,并且i是否存在于整数数组中(如果存在),则再次从1循环到M / i(将循环变量设为j)。
- 再次检查M是否可被j整除,并且j是否存在于整数数组中,如果是,则检查是否存在((M / i)/ j)的剩余数。
- 如果存在,则已形成三元组。为避免重复的三元组,请按排序顺序将它们插入集合中。
- 检查插入三元组后集合的大小是否增加(如果确实如此),然后使用组合函数查找三元组的数量。
- 要查找三元组的数量,将存在以下条件。
- 如果所有的A i ,A j和A k都是唯一的,则组合的数量将为其频率的乘积。
- 如果它们全部相同,那么我们只能选择其中三个,因此公式为 。
- 如果两者相同(让Ai和Aj相等),则计数为 *频率[A k ]
下面是上述方法的实现。
C++
// C++ program to find the
// number of triplets in array
// whose product is equal to M
#include
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 frequency;
// set to store the unique triplets
set > > st;
// count the number of times
// every elememt 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
// mamimum 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
// 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 frequency
= new HashMap<>();
// put to store the unique triplets
Set st = new HashSet();
// count the number of times
// every elememt 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
// mamimum 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 addion,
// 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
输出:
3
时间复杂度: O(N * log N)