给定一个整数数组和一个整数 x ,我需要找到乘积为 x 的数组中无序三元组的数量。我有一个蛮力O( n 3 )解决方案:
int solve(int a[], int n, int x) {
int ans = 0;
for (int i = 0; i < n; ++i)
for (int j = i+1; j < n; ++j)
for (int k = j+1; k < n; ++k)
if(a[i]*a[j]*a[k] == x)
ans++;
return ans;
}
有没有更快的方法,比如说以O( n log n )时间?
答案 0 :(得分:4)
您可以
现在,运行时间将取决于x的质因子pf(x)的数量,特别是O(3 ^ pf(x))。由于x的素因数可以由log(x)限定,因此得出 O(3 ^ log(x)),实际上可以进一步简化精确的底数。
答案 1 :(得分:0)
代码在Java中,但是您知道,想法仍然相同。
时间复杂度为O(n^1.5)
。我检查了10 ^ 5个元素,它工作正常。
这个想法是-
a[i]*a[j]*a[k] == x
为true
,则所有这3个都必须是x
的因数。因此,如果是x%a[i] == 0
,我会寻找所有在x/a[i]
时间内乘以sqrt(x/a[i])
的因素(对)。因为我们对列表中的每个元素都进行了处理,所以复杂性如下-
因此,总复杂度=渐近地为O(n)+ O(n * n ^ 0.5)= O(n ^ 1.5)。
假设-我正在考虑将元组视为数组中具有不同索引的三元组。
更新-当前代码将相同索引i,j,k
的不同排列视为不同的元组。您可以通过将|
(管道)分隔开来附加一个以三元组索引存储为字符串的映射来解决此问题。
import java.util.*;
import java.io.*;
class Solution{
public static void main(String args[]) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] s = br.readLine().split("\\s");
int[] a = new int[n];
for(int i=0;i<n;++i){
a[i] = Integer.parseInt(s[i]);
}
int x = Integer.parseInt(br.readLine());
System.out.println(solve(a,n,x));
}
private static long solve(int a[], int n, int x) {
long tuples = 0;
Map<Integer,Integer> elements = new HashMap<>();
for(int i=0;i<a.length;++i){
elements.put(a[i],elements.getOrDefault(a[i],0) + 1);
}
for(int i=0;i<a.length;++i){
if(x%a[i] == 0){
tuples += factorPairs(x/a[i],elements,a[i]);
}
}
return tuples;
}
private static long factorPairs(int x,Map<Integer,Integer> elements,int factor1){
long pairs = 0;
for(int i=1;i*i<=x;++i){
int second = i;
int third = x/i;
if(second*third == x && elements.containsKey(second) && elements.containsKey(third)){
long second_cnt = elements.get(second) - (second == factor1 ? 1 : 0);
long third_cnt = elements.get(third) - (third == factor1 ? 1 : 0);
pairs += second_cnt * third_cnt;
}
}
return pairs;
}
}