计算乘积为x的三元组数

时间:2018-08-14 14:04:37

标签: c++ algorithm data-structures

给定一个整数数组和一个整数 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 )时间?

2 个答案:

答案 0 :(得分:4)

您可以

  1. 将a中的所有元素放入哈希表中-O(n)
  2. 分解x-O(sqrt(x))
  3. 建立x的所有可能三元除数-O(3 ^ log(x))
  4. 在哈希表中搜索这些三元组-O(1)
  5. 如果存在三元组,请增加您的计数器-O(1)

现在,运行时间将取决于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] == xtrue,则所有这3个都必须是x的因数。因此,如果是x%a[i] == 0,我会寻找所有在x/a[i]时间内乘以sqrt(x/a[i])的因素(对)。
  • 因为我们对列表中的每个元素都进行了处理,所以复杂性如下-

    • O(n)用于向地图添加元素。
    • O(n * n ^ 0.5)用于检查三元组。

因此,总复杂度=渐近地为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;   
    }
}