We present three canonical approaches: a naive method (for clarity), the classic Sieve of Eratosthenes, and the linear (Euler) sieve. All three generate primes <= N (the naive method is included for completeness; prefer sieves for large N).
#include<vector>usingnamespace std;
classSolution {
public: vector<int> primesUpto(int n) {
vector<int> ans;
if (n <2) return ans;
for (int k =2; k <= n; ++k) {
bool is_prime = true;
for (int d =2; 1LL* d * d <= k; ++d) {
if (k % d ==0) { is_prime = false; break; }
}
if (is_prime) ans.push_back(k);
}
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
classSolution {
public List<Integer>primesUpto(int n) {
List<Integer> ans =new ArrayList<>();
if (n < 2) return ans;
for (int k = 2; k <= n; ++k) {
boolean isPrime =true;
for (int d = 2; 1L * d * d <= k; ++d) {
if (k % d == 0) { isPrime =false; break; }
}
if (isPrime) ans.add(k);
}
return ans;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
classSolution:
defprimesUpto(self, n: int) -> list[int]:
ans: list[int] = []
if n <2:
return ans
for k in range(2, n+1):
is_prime =True d =2while d * d <= k:
if k % d ==0:
is_prime =Falsebreak d +=1if is_prime:
ans.append(k)
return ans
⏰ Time complexity: O(N * sqrt(N)) — for each k up to N we do trial division up to sqrt(k), so total work is proportional to the sum of sqrt(k) over k = 2..N (≈ N * sqrt(N) in worst-case reasoning).
🧺 Space complexity: O(1) extra space (excluding the output list of primes).
⏰ Time complexity: O(n log log n) in practice — the cost of marking multiples dominates but is sublinear per element; this is the classic bound for the sieve.
🧺 Space complexity: O(n), for the isPrime boolean array and the output list.
The Euler (linear) sieve visits every integer once, and for each number it marks composites using the list of primes discovered so far, guaranteeing each composite is marked exactly once by its smallest prime factor.
import java.util.ArrayList;
import java.util.List;
classSolution {
public List<Integer>primesUpto(int n) {
List<Integer> primes =new ArrayList<>();
if (n < 2) return primes;
int[] lp =newint[n + 1];
for (int i = 2; i <= n; ++i) {
if (lp[i]== 0) { lp[i]= i; primes.add(i); }
for (int p : primes) {
long v = 1L * p * i;
if (p > lp[i]|| v > n) break;
lp[(int)v]= p;
}
}
return primes;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
classSolution:
defprimesUpto(self, n: int) -> list[int]:
if n <2:
return []
lp = [0] * (n +1)
primes: list[int] = []
for i in range(2, n +1):
if lp[i] ==0:
lp[i] = i
primes.append(i)
for p in primes:
v = p * i
if p > lp[i] or v > n:
break lp[v] = p
return primes