Before attempting this problem, you should be comfortable with:
The most straightforward way to count primes is to check each number individually. A number is prime if it has no divisors other than 1 and itself. We can optimize the divisibility check by only testing divisors up to the square root of the number, since if a number has a factor larger than its square root, it must also have a corresponding factor smaller than its square root.
res to 0.2 to n-1:2 to the square root of the current number divides it evenly.Instead of checking each number for primality, we can use the Sieve of Eratosthenes to efficiently mark composite numbers. The key insight is that when we find a prime number, all of its multiples must be composite. By marking these multiples, we eliminate the need to check them later. We start marking from the square of each prime because smaller multiples would have already been marked by smaller primes.
sieve of size n, initialized to false (all numbers assumed prime).res to 0.2 to n-1:sieve[num] is false):num*num as composite.The problem asks for primes strictly less than n, not less than or equal to. Using range(2, n + 1) or i <= n will include n itself if it's prime.
# Wrong: includes n
for num in range(2, n + 1):
# Correct: excludes n
for num in range(2, n):When starting the sieve from i * i, this multiplication can overflow for large values. Use long or cast before multiplying.
// Overflow risk when i is large
for (int j = i * i; j < n; j += i)
// Safe: use long arithmetic
for (long j = (long) i * i; j < n; j += i)There are no primes less than 2. Failing to handle edge cases like n = 0, n = 1, or n = 2 can cause array index errors or incorrect results.