mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-09-20 07:43:04 +08:00
Merge 7fd168d7d0
into ca3d16dcce
This commit is contained in:
commit
107e239366
44
src/algorithms/math/linear-prime-sieve/README.md
Normal file
44
src/algorithms/math/linear-prime-sieve/README.md
Normal 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).
|
@ -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,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
35
src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js
Normal file
35
src/algorithms/math/linear-prime-sieve/linearPrimeSieve.js
Normal 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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user