Topics › Basics › Know Basic Maths
Print all Divisors
Java source ↗ Edit this article ↗
Jump to code:
Problem
You are given a positive integer n. Return all of its positive divisors (every d with n % d == 0) in increasing order. 1 and n are always included.
Constraints: 1 ≤ n ≤ 2^31 - 1. The number of divisors k is small compared to n (an int has at most 1600 divisors), so the output is never the bottleneck; the search for them is.
Example 1
n = 36
answer = [1, 2, 3, 4, 6, 9, 12, 18, 36]
Example 2
n = 13
answer = [1, 13] // 13 is prime
Example 3
n = 1
answer = [1]
Approach 1: Brute force, test every candidate
Intuition. A divisor of n is at most n, so test every integer from 1 to n with one modulo operation each. Because candidates are visited in increasing order, the output comes out sorted for free.
Algorithm.
- Create an empty list.
- For
dfrom1ton: ifn % d == 0, appendd. - Return the list.
static List<Integer> bruteForce(int n) {
List<Integer> result = new ArrayList<>();
for (int d = 1; d <= n; d++) {
if (n % d == 0) result.add(d);
}
return result;
}
Complexity. Time O(n), one % per candidate; for n = 10^9 that is a billion operations. Space O(k) for the k divisors.
An easy halving is to stop at n / 2 and append n manually, since no divisor other than n exceeds n / 2. That is still O(n). The real improvement comes from noticing that divisors pair up.
Approach 2: Better, divisors come in pairs
Intuition. If d divides n, then so does n / d, and one of the two is at most sqrt(n): if both were larger than sqrt(n), their product would exceed n. So every divisor is either some d ≤ sqrt(n) or the partner n / d of such a d. Scanning only 1..sqrt(n) and emitting both members of each pair finds everything.
Two details. When n is a perfect square, d = sqrt(n) is its own partner, so add it once. And the pairs come out in a mixed order (1, 36, 2, 18, 3, 12, ...), so sort at the end.
Algorithm.
- For
d = 1whiled * d ≤ n:- if
n % d == 0, addd; ifd != n / d, also addn / d.
- if
- Sort the list and return it.
static List<Integer> better(int n) {
List<Integer> result = new ArrayList<>();
for (int d = 1; (long) d * d <= n; d++) {
if (n % d == 0) {
result.add(d);
if (d != n / d) result.add(n / d);
}
}
Collections.sort(result);
return result;
}
Complexity. Time O(sqrt(n) + k log k): about 46341 iterations for the largest int, plus a sort of the k divisors. Space O(k).
The loop condition is written as (long) d * d <= n rather than d <= Math.sqrt(n) for two reasons: it avoids floating-point rounding at perfect squares, and the cast prevents d * d from overflowing int when n is close to 2^31 - 1 (there d reaches 46341 and 46341^2 = 2147488281 would wrap to a negative number, making the loop run far too long or forever).
Approach 3: Optimal, two lists instead of a sort
Intuition. The small divisors d are discovered in increasing order, and their partners n / d are discovered in decreasing order. Keep them in two separate lists. The answer is the first list followed by the second list reversed; no comparison sort is needed, and we still visit each candidate once.
Algorithm.
small = [],large = [].- For
d = 1whiled * d ≤ n: ifn % d == 0, appenddtosmall; ifd != n / d, appendn / dtolarge. - Append the elements of
largetosmallfrom last to first. - Return
small.
static List<Integer> optimal(int n) {
List<Integer> small = new ArrayList<>();
List<Integer> large = new ArrayList<>();
for (int d = 1; (long) d * d <= n; d++) {
if (n % d == 0) {
small.add(d);
if (d != n / d) large.add(n / d);
}
}
for (int i = large.size() - 1; i >= 0; i--) small.add(large.get(i));
return small;
}
Dry run on n = 36 (sqrt(36) = 6):
| d | 36 % d == 0? | small | large |
|---|---|---|---|
| 1 | yes | [1] | [36] |
| 2 | yes | [1, 2] | [36, 18] |
| 3 | yes | [1, 2, 3] | [36, 18, 12] |
| 4 | yes | [1, 2, 3, 4] | [36, 18, 12, 9] |
| 5 | no | ||
| 6 | yes, and 6 == 36 / 6 | [1, 2, 3, 4, 6] | unchanged |
Appending large in reverse gives [1, 2, 3, 4, 6, 9, 12, 18, 36].
Complexity. Time O(sqrt(n)), with no sort. Space O(k) for the two lists (the output itself).
In practice the sort in Approach 2 is negligible because k is tiny, so both are fine in an interview; Approach 3 is simply the cleaner argument. If you need only the count or the sum of divisors, drop the lists and accumulate a counter or a long sum in the same loop.
Edge cases and pitfalls
n = 1. The only divisor is1, and1 == 1 / 1, so the perfect-square guard must stop it from being added twice.- Perfect squares.
36has6as a divisor exactly once. Forgettingif (d != n / d)prints it twice. - Primes. The loop finds only
d = 1and its partnern; output[1, n]. - Overflow in
d * d. FornnearInteger.MAX_VALUEthe square of46341overflowsint. Cast tolongin the loop condition. The tests includeInteger.MAX_VALUE(which is prime, so the answer is[1, 2147483647]). Math.sqrtrounding.(int) Math.sqrt(n)is usually right but can be off by one at perfect squares on some platforms; thed * d <= nform is exact.- Large inputs on the brute force.
10^9 + 7takes a billion iterations with Approach 1 and about 31623 with the others; the tests only run the brute force on smallnand compare the fast versions against it. - Order of output. The problem wants increasing order. The pair-based scan does not produce it directly; either sort or use the two-list merge.
Related problems
- Check for Prime Number uses the same
sqrt(n)bound to decide whether any divisor other than1andnexists. - Divisors of a Number revisits this problem in the advanced-maths step.
- GCD of Two Numbers finds the largest shared divisor without enumerating any of them.
- Prime factorisation of a Number and Print Prime Factors of a Number use the same scan but only keep prime divisors.