📜  乘积为完全平方数的数组中的对数(1)

📅  最后修改于: 2023-12-03 15:36:02.120000             🧑  作者: Mango

乘积为完全平方数的数组中的对数

问题

给定一个整数数组,求其中的乘积为完全平方数的不重复数对的个数。

思路

如果两个数乘积为完全平方数,那么它们的质因数分解中,相同的质因数个数必须为偶数个。因此,我们可以对数组中的每个数进行质因数分解,并将同样的质因数合并为一个集合。最终,对所有集合中的数对进行组合,即可得到结果。

因为涉及到质因数分解和集合的操作,我们可以使用 HashMap 来存储每个数的质因数集合,key 为集合的哈希值,value 为集合中的数的个数。然后,对所有集合中的数对进行组合,计算符合条件的数对个数即可。

代码
public int numSquarefulPerms(int[] A) {
    int n = A.length;
    Map<Integer, Integer> count = new HashMap<>();
    Map<Integer, Set<Integer>> factors = new HashMap<>();
    for (int num : A) {
        count.put(num, count.getOrDefault(num, 0) + 1);
        factors.put(num, new HashSet<>());
    }
    for (int num : count.keySet()) {
        for (int factor = 1; factor <= (int) Math.sqrt(num); factor++) {
            if (num % factor == 0) {
                int anotherFactor = num / factor;
                if (count.containsKey(anotherFactor)) {
                    factors.get(num).add(factor);
                    factors.get(num).add(anotherFactor);
                }
            }
        }
    }
    int[] result = {0};
    Set<Integer> used = new HashSet<>();
    for (int num : count.keySet()) {
        backtracking(count, factors, used, num, n - 1, result);
    }
    return result[0];
}

private void backtracking(Map<Integer, Integer> count, Map<Integer, Set<Integer>> factors, Set<Integer> used, int cur, int remain, int[] result) {
    count.put(cur, count.get(cur) - 1);
    used.add(cur);
    if (remain == 0) {
        result[0]++;
    } else if (factors.containsKey(cur)) {
        for (int factor : factors.get(cur)) {
            if (!used.contains(factor) && count.get(factor) > 0) {
                backtracking(count, factors, used, factor, remain - 1, result);
            }
        }
    }
    used.remove(cur);
    count.put(cur, count.get(cur) + 1);
}
复杂度分析
  • 时间复杂度:O(n^(1.5+n/2))。其中,n 是数组 A 的长度。因为在最坏情况下,数组 A 中的所有数都是互不相同的,且所有数都是完全平方数,那么最大的因子个数为 sqrt(10^9) = 31623,假设数组 A 中每个数都有 31623 个因子,那么每个数都要进行 31623 次递归,共需要递归 n 次。递归的时间复杂度为 O(n!),因此总时间复杂度为 O(n^(1.5+n/2))。
  • 空间复杂度:O(n^2)。我们需要使用 HashMap 存储每个数的质因数集合,以及递归时的 used 集合,因此空间复杂度为 O(n^2)。