Count Primes
Problem (restated)
Given an integer n, return how many primes are strictly less than n.
Intuition
Trial-dividing every candidate is O(n √n). The sieve marks composites in bulk: for each prime p, strike multiples starting at p² (smaller multiples were already hit by a smaller prime).
Approaches
Sieve of Eratosthenes
UnverifiedIdea. Boolean array of size n, 0 and 1 false. For p from 2 while p² < n, if p is still prime, mark p², p²+p, …. Count remaining trues.
Walkthrough. n = 10 → primes 2, 3, 5, 7 → 4. n ≤ 2 → 0.
Trade-offs. Linear space is the cost of the speed. Start crossing at p², not 2p. The answer is primes less than n, so the array is length n, not n+1.
export function countPrimes(n: number): number {
if (n <= 2) return 0;
const prime = new Array<boolean>(n).fill(true);
prime[0] = false;
prime[1] = false;
for (let p = 2; p * p < n; p++) {
if (!prime[p]) continue;
for (let m = p * p; m < n; m += p) prime[m] = false;
}
let c = 0;
for (let i = 2; i < n; i++) if (prime[i]) c++;
return c;
}
export function countPrimes(n: number): number {
if (n <= 2) return 0;
const prime = new Array<boolean>(n).fill(true);
prime[0] = false;
prime[1] = false;
for (let p = 2; p * p < n; p++) {
if (!prime[p]) continue;
for (let m = p * p; m < n; m += p) prime[m] = false;
}
let c = 0;
for (let i = 2; i < n; i++) if (prime[i]) c++;
return c;
}
Template connection
Sieve shape of Math & Number Theory: boolean array, cross out from p*p. Off-by-one on “strictly less than n” is the usual trap.
Reflection
- 0 and 1 are not prime. For each prime
pwithp * p < n, mark multiples starting atp * p. The answer is how many entries stay unmarked. - Start the crossing at
p * p. Smaller multiples were already crossed by an earlier prime. n <= 2answers 0.n = 3answers 1.p * pcan overflow a narrow integer.