AlgoMaster Logo

Prime Sieve

Last Updated: March 31, 2026

5 min read

Prime numbers appear in many coding interview problems, especially those involving factorization, divisibility, and number theory. A naive approach to checking primes works for small inputs, but quickly becomes too slow when constraints grow.

This is where the Prime Sieve comes in. Instead of checking each number independently, it precomputes all prime numbers up to a limit in an efficient way. This shift from repeated work to preprocessing is a common optimization pattern in interviews.

In this chapter, we will build an intuition for how the sieve works, understand why it is efficient, and learn how to apply it in problems that involve primes and factorization.

What Makes a Number Prime?

A prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself. The first few primes are 2, 3, 5, 7, 11, 13, 17, 19, 23, 29.

A few things to note:

  • 1 is not a prime number (by definition).
  • 2 is the only even prime. Every other even number is divisible by 2.
  • If a number n has no divisors up to sqrt(n), it is prime. This is because if n = a * b where both a and b are greater than sqrt(n), then a * b > n, which is a contradiction.

This leads us to two fundamentally different approaches: checking one number at a time (trial division) versus generating all primes up to a limit (sieving).

Approach 1: Trial Division (Brute Force Primality Test)

The simplest way to check if a number n is prime is to test whether any integer from 2 to sqrt(n) divides it evenly.

Why sqrt(n)? If n has a factor larger than sqrt(n), the paired factor must be smaller than sqrt(n). So we only need to check up to the square root.

Algorithm:

  1. If n <= 1, return false.
  2. If n <= 3, return true.
  3. If n is divisible by 2 or 3, return false.
  4. Check all numbers of the form 6k +/- 1 up to sqrt(n). (All primes greater than 3 are of this form.)

This works perfectly for checking individual numbers, but if you need to find all primes up to n, calling this function for every number gives O(n * sqrt(n)) total time. That is where the sieve becomes essential.

Approach 2: Sieve of Eratosthenes

The Sieve of Eratosthenes flips the problem on its head. Instead of checking each number individually, we start by assuming every number is prime, then systematically eliminate the composite ones.

Algorithm:

  • Create a boolean array isPrime[0..n], initialized to true.
  • Mark isPrime[0] and isPrime[1] as false.
  • For each number p starting from 2:
    • If isPrime[p] is true, then p is prime.
    • Mark all multiples of p (starting from p * p) as false.
  • Continue until p * p > n.
  • All indices still marked true are prime.

Why start marking from p * p?

Because all smaller multiples of p (like 2p, 3p, ..., (p-1) * p) have already been marked as composite by smaller primes. For example, when p = 5, we do not need to mark 10 (already handled by 2), 15 (already handled by 3), or 20 (already handled by 2). We start directly at 25.

Approach 3: Prime Factorization Using Smallest Prime Factor (SPF) Sieve

A powerful variation of the sieve precomputes the smallest prime factor for every number. Once you have this, you can factorize any number up to n in O(log n) time by repeatedly dividing by the smallest prime factor.

Algorithm:

  1. Create an array spf[0..n] where spf[i] = i initially (every number is its own smallest factor).
  2. Run the sieve: for each prime p, set spf[m] = p for all multiples m of p where spf[m] has not been updated yet (i.e., spf[m] == m).
  3. To factorize a number x: repeatedly divide x by spf[x] until x becomes 1.

This is especially useful when you need to factorize many numbers. Building the SPF sieve is O(n log log n), and each factorization is O(log n).

Example Walkthrough: Sieve of Eratosthenes for n = 30

Let us trace through the algorithm step by step. We start with all numbers from 2 to 30 marked as prime (T = true).

Step 1: p = 2 (prime). Mark multiples starting from 2*2 = 4: cross off 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30.

Step 2: p = 3 (still marked prime). Mark multiples starting from 3*3 = 9: cross off 9, 15, 21, 27. (Note: 6, 12, 18, 24, 30 were already crossed off by 2.)

Step 3: p = 4 (marked false). Skip it.

Step 4: p = 5 (still marked prime). Mark multiples starting from 5*5 = 25: cross off 25. (30 is already crossed off.)

Step 5: p = 6 (stop). Since 6*6 = 36 > 30, we are done.

Primes up to 30: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29. That is 10 primes.

Notice how few steps it took. We only needed to sieve with p = 2, 3, and 5. The sqrt(30) boundary means we stop early, and the p*p starting point means we skip redundant work.

Implementation

Trial Division: isPrime

Sieve of Eratosthenes (Count Primes, LeetCode 204)

Given an integer n, return the number of primes strictly less than n.

Prime Factorization Using SPF Sieve

Complexity Analysis

AlgorithmTime ComplexitySpace ComplexityUse Case
Trial DivisionO(sqrt(n)) per queryO(1)Checking a single number
Sieve of EratosthenesO(n log log n)O(n)Finding all primes up to n
SPF Sieve (build)O(n log log n)O(n)Precomputing smallest prime factors
SPF FactorizationO(log n) per queryO(log n)Factorizing after sieve is built

Why O(n log log n) for the sieve? The total number of composite markings is:

n/2 + n/3 + n/5 + n/7 + ... (sum over all primes p <= n)

By Mertens' theorem, the sum of reciprocals of primes up to n is approximately log(log(n)). Multiplying by n gives O(n log log n). In practice, this is nearly linear. For n = 10 million, log(log(n)) is about 3.