Mistakes explained
This code was correct, however the testing software failed some hidden test cases where the list of nums was 10000 because of "time out", meaning that it took too long.
I would not say that the code is correct (since there's a flaw in it), rather you had no opportunity to see it failing on a small input.
In the inner for
-loop you're initializing the staring value of the index j
to i
- int j = i
. Which means at the first iteration of the inner loop, you're adding an element to itself: nums.get(i) + nums.get(j)
and then checking whether it's divisible by 60
.
That's might lead to invalid results. Inner loop should start with j = i + 1
. With this fix, you'll get a correct brute-force solution.
The second issue - terminology.
What your code is counting are not Permutations, but Combinations of pairs of elements (it's not an academical spreading of hairs, the result would be different).
As a simple illustration, suppose the input is [1,2,3]
, and we need Combinations of pairs of elements that are divisible by 3
. There's only one Combination: [1,2]
, but two Permutations: [1,2]
and [2,1]
.
Because in your brute-force solution i < j
always holds true, it's not capable of generating Permutations (since it doesn't revisit the same indices in the inner loop it can only consider [i,j]
, but not [j,i]
), and it produces the number of Combinations.
Now when the problem statement is clarified: "Find the number of Combinations pairs that are divisible by the given number", let's get to the actual solution.
Solution
As @Joachim Sauer has pointed out in the comments, the first step in addressing this problem is to create an array of frequencies of array elements % 60
(like in the first phase of the Counting sort algorithm).
Then we have two cases:
When considering remainder from divisions by 60
in the union ranges [1,29]∪[31,59]
we need to calculate a Cartesian product of frequencies of the corresponding remainders and add it to the total. I.e. frequency(1)xfrequency(59)
, frequency(2)xfrequency(58)
, ... all the way up to frequency(29)xfrequency(31)
. Note that we shouldn't touch frequency(0)
and frequency(30)
(they need to be treated separately), we should not double count the product, i.e. we should not consider reversed combinations like frequency(59)xfrequency(1)
.
Combinations frequency(0)
and frequency(30)
are a special case because we can combine them only with themselves. And for both cases, we need to calculate a Binomial coefficient according to the following formula:

Where n
is the number of frequencies (for 0
or for 30
), and k
is the number of elements in the combination, which is always equal to 2
.
That's how the implementation might look like (to simplify testing, divisor 60
is not hard-coded, but provided as a method parameter):
public static long getPairCount(List<Integer> list, int divisor) {
int[] freq = new int[divisor]; // frequencies of modulus of array 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 += binomialCoefficient(freq[0], 2 );
if (divisor % 2 == 0 && freq[divisor / 2] > 1) count += binomialCoefficient(divisor / 2, 2 ); // should be only considered if divisor is
return count;
}
public static long binomialCoefficient(int n, int k) {
return factorial(n) / (k * factorial(n - k));
}
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]
}
Output:
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]