Start learning free

LESSON 245 OF 671 · HELPER FUNCTIONS

Perfect Numbers in Java: Sum the Divisors With a Helper

Practice Read the full explanation

You get an array of integers nums. Return the perfect numbers among them, in the same order.

A number is perfect when it equals the sum of its divisors smaller than itself. For example, 6 is perfect, because 1 + 2 + 3 = 6. The number 1 is not perfect. It has no smaller divisors, so its sum is 0.

If a perfect number appears twice, it is kept twice. If no number is perfect, the result is empty.

The work is split between two functions. The first one is a helper. It gets one number and returns the sum of its divisors smaller than itself. The second one is the function that is graded. It keeps every number that equals the sum the helper returns for it.

 

Example 1:

Input: nums = [6, 8, 28, 12]
Output: [6, 28]
Explanation: 6 = 1 + 2 + 3.
28 = 1 + 2 + 4 + 7 + 14.
For 8, the sum is 1 + 2 + 4 = 7.
For 12, the sum is 1 + 2 + 3 + 4 + 6 = 16.

Example 2:

Input: nums = [1, 5, 10]
Output: []
Explanation: The sum for 1 is 0.
The sum for 5 is 1.
The sum for 10 is 1 + 2 + 5 = 8.

Example 3:

Input: nums = [496, 6, 6]
Output: [496, 6, 6]
Explanation: 496 is perfect too.
6 appears twice, so it is kept twice.

 

Constraints:

  • nums has 1 to 20 numbers.
  • Every number is between 1 and 10,000.
STEP 1 OF 8
    Ctrl + Enter to check

    JAVA · HELPER FUNCTIONS

    Perfect Numbers in Java, explained

    Problem overview

    The method perfectNumbers receives an array of integers nums and returns the perfect numbers among them, in the same order. A number is perfect when it equals the sum of its divisors that are smaller than itself. For example, 6 is perfect, because 1 + 2 + 3 = 6. The number 1 is not perfect: it has no smaller divisors, so its sum is 0. A perfect number that appears twice is kept twice. If none is perfect, the result is empty.

    For [6, 8, 28, 12] the result is [6, 28]. The sum for 8 is 1 + 2 + 4 = 7, and for 12 it is 1 + 2 + 3 + 4 + 6 = 16. For [1, 5, 10] the result is []: the sums are 0, 1 and 8. For [496, 6, 6] every number is perfect, so the result is [496, 6, 6]. There are 1 to 20 numbers, each between 1 and 10,000.

    Approach: a helper for one number

    The work is split in two. The helper sumOfDivisors takes one number n and returns the sum of its divisors smaller than n. perfectNumbers loops over the array and keeps each number that equals the helper's answer for it.

    To find the divisors of n, try every d from 1 up to, but not including, n. A number d divides n evenly when n % d == 0, that is, when the remainder is 0. Each such d is added to a running total. With numbers up to 10,000 and at most 20 of them, trying every d is fast enough.

    Step by step

    1. In sumOfDivisors, create an int named total, starting at 0.
    2. Write a for loop with d starting at 1 and running while d < n. The number n itself is left out.
    3. Inside the loop, if n % d == 0, add d to total.
    4. After the loop, return total.
    5. In perfectNumbers, create an empty List<Integer> named perfect.
    6. Loop over nums with an int named num.
    7. If sumOfDivisors(num) equals num, add num to perfect.
    8. After the loop, return perfect.

    The solution in Java

    class Solution {
        public int sumOfDivisors(int n) {
            int total = 0;
            for (int d = 1; d < n; d++) {
                if (n % d == 0) {
                    total += d;
                }
            }
            return total;
        }
    
        public List<Integer> perfectNumbers(int[] nums) {
            List<Integer> perfect = new ArrayList<>();
            for (int num : nums) {
                if (sumOfDivisors(num) == num) {
                    perfect.add(num);
                }
            }
            return perfect;
        }
    }

    Some Java details:

    • The loop uses d < n, not d <= n. With <= the number would count itself as a divisor and the sum would always be too large by n.
    • For n = 1 the loop never runs, so the helper returns 0 and 1 is correctly rejected.
    • Both sides of sumOfDivisors(num) == num are int, so == compares values. It would be a trap only with Integer objects.
    • The loop variable num is an int, and perfect.add(num) boxes it into an Integer automatically.

    The helper gives these sums: 6 gives 6, 8 gives 7, 28 gives 28, 12 gives 16, 1 gives 0, 5 gives 1, 10 gives 8 and 496 gives 496. Only 6, 28 and 496 equal their own sums.

    Edge cases and common mistakes

    • Counting the number itself. A loop that includes n makes every number's sum at least n, and the check == num then fails for 6 (the sum would be 12).
    • Starting d at 0. n % 0 throws an ArithmeticException for ints. Start at 1.
    • The number 1. Its sum is 0, so it is not perfect.
    • Returning inside the loop. The return perfect goes after the loop.
    • Repeated numbers. Nothing removes duplicates, so 6 appears twice in the result for [496, 6, 6].

    Why trying every divisor is fine here

    For each number the helper does up to 9,999 checks, and there are at most 20 numbers, so the whole method does fewer than 200,000 remainder checks. That is instant. A faster helper could stop at the square root of n and add both divisors of each pair, but it needs special care for perfect squares, and this input size doesn't call for it.

    Walking through the first example

    For [6, 8, 28, 12], the loop asks the helper about each number in turn. For 6, the divisors below 6 are 1, 2 and 3, which sum to 6, so 6 is added to perfect. For 8, the divisors are 1, 2 and 4. They sum to 7, which is not 8, so 8 is skipped. For 28, the sum is 28, so it is added. For 12 the sum is 16, so it is skipped. The loop ends with [6, 28], in the order of the input.

    Keeping the jobs apart

    The helper knows how to sum divisors and nothing about perfect numbers. The main method knows the rule for a perfect number and nothing about divisors. If an answer is wrong, call sumOfDivisors alone on a number like 6 or 12 to see which half has the bug. The sum for 12 should be 16, which is more than 12, so 12 must not be in the result.

    Testing

    Running the solution on the three examples gives:

    [6, 28]
    []
    [496, 6, 6]
    Keep going with Java500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free