Sieve of Eratosthenes
Algorithm · Core
Step through it: Number Theory pattern
Step 1 of 5
Goal: the greatest common divisor of 48 and 18. Key fact: the answer stays the same if you replace (a, b) with (b, the remainder of a ÷ b). The numbers shrink quickly.
Step 2 of 5
48 ÷ 18 leaves remainder 12, so carry on with (18, 12).
Step 3 of 5
18 ÷ 12 leaves 6: carry on with (12, 6).
Step 4 of 5
12 ÷ 6 leaves 0, so stop: the answer is 6. Remainders shrink fast, so only a few steps (O(log n)). The least common multiple follows: lcm = a × b ÷ gcd. These are number theory tools.
Step 5 of 5
Your turn.
Complexity
The algorithm has a complexity of O(n log(log n)).
The Sieve of Eratosthenes is an algorithm for finding all prime numbers up to some limit n.
It is attributed to Eratosthenes of Cyrene, an ancient Greek mathematician.
How it works
- Create a boolean array of
n + 1positions (to represent the numbers0throughn) - Set positions
0and1tofalse, and the rest totrue - Start at position
p = 2(the first prime number) - Mark as
falseall the multiples ofp(that is, positions2 * p,3 * p,4 * p... until you reach the end of the array) - Find the first position greater than
pthat istruein the array. If there is no such position, stop. Otherwise, letpequal this new number (which is the next prime), and repeat from step 4
When the algorithm terminates, the numbers remaining true in the array are all
the primes below n.
An improvement of this algorithm is, in step 4, start marking multiples
of p from p * p, and not from 2 * p. The reason why this works is because,
at that point, smaller multiples of p will have already been marked false.
Example
Code
/**
* @param {number} maxNumber
* @return {number[]}
*/
export default function sieveOfEratosthenes(maxNumber) {
const isPrime = new Array(maxNumber + 1).fill(true);
isPrime[0] = false;
isPrime[1] = false;
const primes = [];
for (let number = 2; number <= maxNumber; number += 1) {
if (isPrime[number] === true) {
primes.push(number);
/*
* Optimisation.
* Start marking multiples of `p` from `p * p`, and not from `2 * p`.
* The reason why this works is because, at that point, smaller multiples
* of `p` will have already been marked `false`.
*
* Warning: When working with really big numbers, the following line may cause overflow
* In that case, it can be changed to:
* let nextNumber = 2 * number;
*/
let nextNumber = number * number;
while (nextNumber <= maxNumber) {
isPrime[nextNumber] = false;
nextNumber += number;
}
}
}
return primes;
}References
Practice
Number Theory
- Greatest Common Divisor of StringsEasy
- Ugly NumberEasy
- Happy NumberEasy
- Plus OneEasy
- Add BinaryEasy
- Excel Sheet Column NumberEasy
- Count PrimesMedium
- Pow(x, n)Medium
- Factorial Trailing ZeroesMedium
- Ugly Number IIMedium
- Multiply StringsMedium
- Divide Two IntegersMedium
- Water and Jug ProblemMedium
- Super PowMedium
- Largest Component Size by Common FactorHard
Spotted a mistake or something unclear? Report it on GitHub.