这段代码是正确的,但是测试软件由于“超时”而未能通过一些隐藏的测试用例,其中 nums 列表为 10000,这意味着它花费的时间太长。
我不会说代码是正确的(因为它有一个缺陷),而是你没有机会看到它在一个小的输入上失败了。
在内部for循环中,您将索引j的起始值初始化为i-int j = i。这意味着在内部循环的第一次迭代中,您要将一个元素添加到本身: nums.get(i) + nums.get(j) 然后检查它是否可以被 60 整除。
这可能会导致无效结果。内循环应以j = i + 1 开头。通过此修复,您将获得正确的暴力解决方案。
第二题——术语.
您的代码计算的是不是Permutations,但Combinations成对的元素(这不是学术上的散布,结果会有所不同)。
举个简单的例子,假设输入是 [1,2,3],我们需要可被 3 整除的元素对的组合。只有一种组合 [1,2],但有两种排列:[1,2] 和 [2,1]。
因为在您的蛮力解决方案中,i < j 始终成立,所以它无法生成排列(因为它不会在内部循环中重新访问相同的索引,所以它只能考虑[i,j],而不是[j,i]),并且它产生组合的数量(因此问题的标题不正确,考虑修复它)。
现在当问题陈述被澄清时:“找出可被给定数字整除的组合对的数量”,让我们开始实际的解决方案。
解决方案
作为@约阿希姆绍尔在 cmets 中指出,解决此问题的第一步是创建一个数组元素频率数组 % 60(就像在计数排序算法的第一阶段)。
那么我们有两种情况:
-
当考虑在[1,59]范围内除以60的余数时,我们需要计算Cartesian product的频率和相应的余数并将其加到总数中。 IE。 frequency(1)xfrequency(59)、frequency(2)xfrequency(58)、...一直到frequency(29)xfrequency(31)。笔记我们不应该接触frequency(0)和frequency(30)(它们需要分开处理),我们不应该重复计算产品,即我们不应该考虑像frequency(59)xfrequency(1)这样的反向组合。
-
组合 frequency(0) 和 frequency(30) 是一种特殊情况,因为我们只能将它们组合在一起。对于这两种情况,我们都需要根据以下公式计算二项式系数:
其中n 是频率数(0 或30),k 是组合中的元素数,始终等于2。
这就是实现的样子(为了简化测试除数 60 不是硬编码的,而是作为方法参数提供的):
public static long getPairCount(List<Integer> list, int divisor) {
int[] freq = new int[divisor]; // frequencies of modulus of list elements
for (int next : list) freq[next % divisor]++;
long count = 0;
for (int left = 1, right = divisor - 1; left < divisor / 2 + divisor % 2; left++, right--) {
count += ((long) freq[left]) * freq[right]; // a cartesian product gives a number of ways to form a pair
}
// Special cases: remainder 0 and remainder divisor / 2 - now with dialing with pure Combinations
// and instead Cartesian product a Binomial coefficient needs to be calculated
if (freq[0] > 1) count += factorial(freq[0]) / 2 * factorial(freq[0] - 2);
if (divisor % 2 == 0 && freq[divisor / 2] > 1) count += factorial(freq[0]) / 2 * factorial(freq[0] - 2); // should be only considered if divisor is
return count;
}
public static long factorial(int num) {
long result = 1;
for (int i = 1; i <= num; i++) result *= i;
return result;
}
main()
public static void main(String[] args) {
System.out.println(getPairCount(List.of(1, 2, 3), 3)); // [1, 2]
System.out.println(getPairCount(List.of(1, 2, 3, 1, 2, 3, 4, 5), 7)); // [2, 5] x 2, [3, 4] x 2
System.out.println(getPairCount(List.of(1, 2, 3, 1, 2, 3, 4, 5), 5)); // [2, 3] x 4, [1, 4] x 2
System.out.println(getPairCount(List.of(1, 2, 3, 1, 2, 3, 4, 5, 5), 5)); // [2, 3] x 4, [1, 4] x 2, [5, 5]
}
输出:
1 // [1, 2]
4 // [2, 5] x 2, [3, 4] x 2
6 // [2, 3] x 4, [1, 4] x 2
7 // [2, 3] x 4, [1, 4] x 2, [5, 5]