Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
Given an integer n, return the number of prime numbers that are strictly less than n.
Example 1:
Input: n = 10 Output: 4 Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7.
Example 2:
Input: n = 0 Output: 0
Example 3:
Input: n = 1 Output: 0
Constraints:
0 <= n <= 5 * 106Problem summary: Given an integer n, return the number of prime numbers that are strictly less than n.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Math
10
0
1
ugly-number)ugly-number-ii)perfect-squares)number-of-common-factors)prime-pairs-with-target-sum)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #204: Count Primes
class Solution {
public int countPrimes(int n) {
boolean[] primes = new boolean[n];
Arrays.fill(primes, true);
int ans = 0;
for (int i = 2; i < n; ++i) {
if (primes[i]) {
++ans;
for (int j = i + i; j < n; j += i) {
primes[j] = false;
}
}
}
return ans;
}
}
// Accepted solution for LeetCode #204: Count Primes
func countPrimes(n int) int {
primes := make([]bool, n)
for i := range primes {
primes[i] = true
}
ans := 0
for i := 2; i < n; i++ {
if primes[i] {
ans++
for j := i + i; j < n; j += i {
primes[j] = false
}
}
}
return ans
}
# Accepted solution for LeetCode #204: Count Primes
class Solution:
def countPrimes(self, n: int) -> int:
primes = [True] * n
ans = 0
for i in range(2, n):
if primes[i]:
ans += 1
for j in range(i + i, n, i):
primes[j] = False
return ans
// Accepted solution for LeetCode #204: Count Primes
struct Solution;
impl Solution {
fn count_primes(n: i32) -> i32 {
if n <= 2 {
return 0;
}
let n: usize = n as usize;
let mut a: Vec<bool> = vec![true; n];
a[0] = false;
a[1] = false;
let mut i: usize = 2;
while i * i < n {
if a[i] {
let mut j = 2;
while j * i < n {
a[i * j] = false;
j += 1;
}
}
i += 1;
}
let sum: i32 = a.iter().fold(0, |sum, &b| if b { sum + 1 } else { sum });
sum
}
}
#[test]
fn test() {
assert_eq!(Solution::count_primes(10), 4);
}
// Accepted solution for LeetCode #204: Count Primes
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #204: Count Primes
// class Solution {
// public int countPrimes(int n) {
// boolean[] primes = new boolean[n];
// Arrays.fill(primes, true);
// int ans = 0;
// for (int i = 2; i < n; ++i) {
// if (primes[i]) {
// ++ans;
// for (int j = i + i; j < n; j += i) {
// primes[j] = false;
// }
// }
// }
// return ans;
// }
// }
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.