Start learning free

LESSON 245 OF 671 · HELPER FUNCTIONS

Perfect Numbers in JavaScript with a Helper Method

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

    JAVASCRIPT · HELPER FUNCTIONS

    Perfect Numbers in JavaScript, explained

    Problem overview

    The method perfectNumbers gets 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. The number 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, and if no number is perfect the result is empty. Each number is between 1 and 10,000, and there are 1 to 20 of them.

    For [6, 8, 28, 12] the answer is [6, 28]. The sum for 8 is 1 + 2 + 4 = 7, and for 12 it is 1 + 2 + 3 + 4 + 6 = 16, so neither matches. For [1, 5, 10] the sums are 0, 1 and 8, so the answer is empty. For [496, 6, 6] all three are perfect, so the answer is [496, 6, 6].

    Approach: a helper for the divisor sum

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

    To find the divisors, try every d from 1 up to n - 1. A number d divides n evenly when the remainder n % d is 0. With numbers up to 10,000 and at most 20 of them, trying every d is fast enough, so no cleverness is needed.

    Step by step

    1. In sumOfDivisors, start total at 0. For n = 1 the loop never runs, so the sum stays 0.
    2. Try every possible divisor: for (let d = 1; d < n; d++). The condition d < n leaves n itself out.
    3. Add the divisors: if n % d == 0, add d to total. For 6, these are 1, 2 and 3.
    4. Return total after the loop.
    5. In perfectNumbers, start with an empty array named perfect.
    6. Loop over the numbers with for (let num of nums). A perfect number that appears twice is visited twice, so it is kept twice.
    7. Compare with the helper: if this.sumOfDivisors(num) == num, push num onto perfect.
    8. Return perfect after the loop.

    The solution in JavaScript

    class Solution {
        sumOfDivisors(n) {
            let total = 0;
            for (let d = 1; d < n; d++) {
                if (n % d == 0) {
                    total += d;
                }
            }
            return total;
        }
        perfectNumbers(nums) {
            let perfect = [];
            for (let num of nums) {
                if (this.sumOfDivisors(num) == num) {
                    perfect.push(num);
                }
            }
            return perfect;
        }
    }
    

    Some details:

    • The remainder operator. n % d is the remainder of the division. It is 0 exactly when d divides n.
    • Calling the helper. Inside the class, use this.sumOfDivisors(num). The call goes straight into the comparison, and the helper's own loop runs once for each number.
    • Whole numbers only. JavaScript numbers are doubles, but integers this small are exact, so == between two sums is safe.

    Following 12 and 28

    For n = 12, the loop tries d from 1 to 11. The values 1, 2, 3, 4 and 6 leave a remainder of 0, so they are added: 1 + 2 + 3 + 4 + 6 = 16. Since 16 is not 12, the number 12 is not perfect, and it is skipped. Notice that the sum can be bigger than the number. For n = 28 the divisors found are 1, 2, 4, 7 and 14, and they add up to 28, so 28 is pushed onto perfect.

    The numbers whose sum is smaller than the number are fine too. For 5 the only divisor is 1, and for 10 the divisors are 1, 2 and 5, giving 8. In both cases the sum is different from the number, so the answer for [1, 5, 10] stays empty.

    Testing

    The helper on single numbers returns these sums: 6 gives 6, 8 gives 7, 12 gives 16, 28 gives 28, 1 gives 0, 5 gives 1 and 10 gives 8. On the statement's examples the solution prints these lines, with an empty line for the second example:

    6 28
    
    496 6 6
    

    The next perfect number after 496 is 8128, which is inside the limit of 10,000. The helper returns 8128 for it, so perfectNumbers([8128]) returns that one number.

    Common mistakes

    • Looping to d <= n. That adds n itself, so the sum for 6 becomes 12 and no number is ever perfect.
    • Starting d at 0. Dividing by zero gives NaN in JavaScript, not an error, and NaN == 0 is false, so the answer would not change. It is still a wrong start: divisors begin at 1.
    • Treating 1 as perfect. Its sum is 0, which is not 1, and the rule handles it with no special case.
    • Returning inside the loop. The method would stop after the first number.
    • Removing duplicates. A perfect number that appears twice is kept twice, as in the third example.
    Keep going with JavaScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free