Mark As Completed Discussion

Good afternoon! Here's our prompt for today.

You're given a number n. Can you write a method sumOfAllPrimes that finds all prime numbers smaller than or equal to n, and returns a sum of them?

Description

For example, we're given the number 15. All prime numbers smaller than 15 are:

2, 3, 5, 7, 11, 13

They sum up to 41, so sumOfAllPrimes(15) would return 41.

Constraints

  • n will always be a non zero positive integer <= 100000
  • Expected time complexity : O(nlogn)
  • Expected space complexity : O(n)

Try to solve this here or in Interactive Mode.

How do I practice this challenge?

JAVASCRIPT
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

Here's how we would solve this problem...

How do I use this guide?

Step 1: Gathering Prime Number Candidates

We'll start by creating an array of integers up to n+1. Since prime numbers must be natural numbers greater than 1, we can discard 0 and 1.

Here's a visual representation of what we're doing:

Gathering Prime Number Candidates

Here's how we initialize our candidates in both JavaScript and Python:

1const n = 4;
2const numsLessThanN = Array.from(
3  { length: n + 1 }, function(val, idx) {
4    return idx;
5  }
6).slice(2);

This provides us with all potential prime number candidates smaller than n.

Step 2: Filtering Prime Numbers

With our candidates ready, we must now filter them to identify the prime numbers.

The Naive Approach

We could manually check each number by looping through every number from 2 up to the current one, verifying if the current number is divisible by any other number. If it's divisible, it's not a prime number!

Here's a simple implementation:

1function isPrime(num) {
2  for (let i = 2; i < num; i++) {
3    if (num % i === 0) return false;
4  }
5  return num > 1;
6}
7
8console.log(isPrime(7));
Efficiency Considerations

While this naive approach works, it's pretty slow. The manual check is an O(n) operation, and since we need to run it for each number less than the input n, the overall function has a time complexity of O(n^2).

Can we improve this? Stay tuned, and we'll explore more efficient ways to identify prime numbers in our next lessons!

JAVASCRIPT
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

The easiest way is through this piece of logic: while a number can be prime and greater than 1, try dividing it by prime numbers greater than its square root. For example, say we have 6-- it's square root is ~2.449. So we try to divide it by 3, the next greater prime number, but we realize it is divisible and thus not prime. We'll expand on the logic for this shortly!

Complexity Of Final Solution
1const primes = numsLessThanN.filter((num) => {
2  let primeCandidate = num - 1;
3
4  while (primeCandidate > 1 && primeCandidate >= Math.sqrt(num)) {
5    if (num % primeCandidate === 0) return false;
6    primeCandidate--;
7  }
8
9  return true;
10});

Complexity of Final Solution

Let n be the input number. We fill an array of size n to keep track of potential prime candidates for O(n) space complexity, and our while loop that updates our array performs roughly log n work over n iterations for O(n log n) time complexity.

Here's why it works: if a number is divisible by a prime number, then it itself is not a prime number.

On the flip side, the number must be divisible beyond its square root. The intuition here saves us several calculations, and can be understood with the following:

  • If n isn't prime, it should be able to be factored into x and y. In our previous example, 6 could be factored into 2 and 3.
  • If both x and y were greater than the square root of n, it would confirm that x * y would produce a number larger than n. In this case, only 3 is larger than the square root.
  • This means at least one of the factors needs to be less than or equal to the square root of n. If we don't find any factors that fit, that are greater than or equal to the square root, we know that n must be a prime number. However, we found 3-- so 6 can't be prime.
Step Four

Let's take the number 7, and run the numbers smaller than it through this filter:

  • Starting at 7, passes the conditions, returns true.
  • 6, we find that 6 is divisible by 3, so remove it.
  • 5 passes the conditions, returns true.
  • 4 is divisible by 2, get rid of it as well.
  • 3 passes the conditions, returns true.
  • 2 passes the conditions, returns true.
  • We throw out 0 and 1 since they're not prime.

So we get 17 once they're summed up.

Step Four

One Pager Cheat Sheet

  • Write a method sumOfAllPrimes that takes a number n and returns the sum of all prime numbers smaller than or equal to n.
  • We can use an array of length n+1 initialized with natural numbers starting from 2, and removing 0 and 1, to programmatically determine what numbers are prime.
  • We can figure out the prime number candidates that are smaller than n with an O(n^2) operation by looping through every number from 2 to the current one and seeing if it is divisible.
  • We can check for prime numbers efficiently by looping over the numbers below n and performing a log n time operation to check divisibility by prime numbers larger than the square root of n.
  • We can use a filter that requires a number to be divisible beyond its square root in order to determine if it is a prime number, which allows us to efficiently find and sum all prime numbers.

This is our final solution.

To visualize the solution and step through the below code, click Visualize the Solution on the right-side menu or the VISUALIZE button in Interactive Mode.

JAVASCRIPT
OUTPUT
:001 > Cmd/Ctrl-Enter to run, Cmd/Ctrl-/ to comment

That's all we've got! Let's move on to the next tutorial.

If you had any problems with this tutorial, check out the main forum thread here.