This commit is contained in:
Sandeep Satheesh 2024-07-17 10:36:58 +09:00 committed by GitHub
commit 107e239366
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 91 additions and 0 deletions

View File

@ -0,0 +1,44 @@
# Linear Prime Sieve
Linear Prime Sieve is an algorithm for finding all prime numbers up to some limit `n` in linear time.
## How it works
1. Create an array `leastPrimeFactor` of `n + 1` positions filled with `0`(to represent the least prime factors of numbers `0` through `n`)
2. Start at position `i = 2` (the first prime number)
3. If the least prime factor of `i` is `0` it means `i` is a prime number, so we add it to our list of `primes`.
4. We start setting the least prime factor for numbers `x`, where x = `p` * `i`, `p` is `x`'s least prime factor and `p` <= `leastPrimeFactor(i)`, we do
this by traversing the list of primes accumulated till now.
5. Increment the value of `i`.
6. We repeat steps 3 through 5 until `i` exceeds `n`.
When the algorithm terminates, all the prime numbers from `0` through `n` will be added to our primes list
## Complexity
The algorithm has a complexity of `O(n)`.
## Proof Of Correctness
In order to prove the time complexity, we need to show that the alogrithm sets all leastPrimeFactor[] correctly, and that every value will be set only once.
If so the algorithm will have linear time complexity, since all the remaining work of the algorithm is of `O(n)`.
We Observe that every number `i` has exactly one representation of form:
`i = leastPrimeFactor[i] * x`, where leastPrimeFactor[i] <= leastPrimeFactor[x].
In our Alogrith, for every `x`, it goes through all prime numbers it could be multiplied by, i.e. all prime numbers up to leastPrimeFactor[x] inclusive,
in order to get the numbers in the form given above.
Hence, the algorithm will go through every composite number exactly once, setting the correct values for leastPrimeFactor[] there.
## References
- David Gries, Jayadev Misra. A Linear Sieve Algorithm for Finding Prime Numbers [1978].
- [CP-Algorithms/Linear-Sieve](https://cp-algorithms.com/algebra/prime-sieve-linear.html).

View File

@ -0,0 +1,12 @@
import linearPrimeSieve from '../linearPrimeSieve';
describe('linearPrimeSieve', () => {
it('should find all primes less than or equal to n', () => {
expect(linearPrimeSieve(5)).toEqual([2, 3, 5]);
expect(linearPrimeSieve(10)).toEqual([2, 3, 5, 7]);
expect(linearPrimeSieve(100)).toEqual([
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
]);
});
});

View File

@ -0,0 +1,35 @@
/**
* @param {number} maxNumber
* @return {number[]}
*/
export default function linearPrimeSieve(maxNumber) {
const primes = [];
// leastPrimeFactor[i] gives us the least prime factor of 'i'
const leastPrimeFactor = new Array(maxNumber + 1).fill(0);
for (let i = 2; i <= maxNumber; i += 1) {
if (!leastPrimeFactor[i]) {
/* leastPrimeFactor[i] = 0 means 'i' itself is its least prime factor,
* i.e 'i' is prime
*/
leastPrimeFactor[i] = i;
primes.push(i);
}
/*
* start setting leastPrimeFactor[] for numbers 'x', where x = p * i, p is x's
* least prime factor and p <= leastPrimeFactor[i]. x = p*i, this representation will
* be unique for any number, therefore leastPrimeFactor[x] will be
* set only once.
*/
let j = 0;
while (j < primes.length) {
if ((primes[j] * i > maxNumber) || (primes[j] > leastPrimeFactor[i])) { break; }
leastPrimeFactor[primes[j] * i] = primes[j];
j += 1;
}
}
return primes;
}