Problem overview
The function isPrime receives a non-negative integer n and returns true if it is prime and false if it is not. A prime is a number greater than 1 whose only divisors are 1 and itself. So 31 is prime, while 6 is not, because 2 and 3 divide it. The numbers 0 and 1 are not prime by definition.
The statement asks for O(n) time and O(1) extra space, so a loop that tries every candidate divisor once is enough.
Approach: look for a divisor between 2 and n - 1
Turn the definition around. A number n is prime exactly when it is at least 2 and no number d with 1 < d < n divides it. That gives a direct algorithm: try each d from 2 up to n - 1, and the moment one divides n evenly, return false. If none does, return true.
The divisibility test is the remainder operator: n % d == 0 means d goes into n with nothing left over. For n = 6, the first candidate is 2, and 6 % 2 is 0, so the loop returns false immediately. For n = 31, no candidate from 2 to 30 gives a remainder of 0, so the loop ends and the function returns true.
This is trial division in its simplest form. It does more work than needed: a divisor larger than the square root of n always pairs with a smaller one, so stopping at the square root would be faster. This lesson keeps the simple version, which fits the stated O(n) budget.
Step by step
- Handle the small numbers first. If
n < 2, returnfalse. This covers 0 and 1, which have no place among the primes. Without this check, the loop would not run for them and the function would wrongly returntrue. - Loop over candidate divisors. Declare
dwith:=in aforloop, start it at 2, and stop beforen. A prime always divides itself, and 1 always divides it, so those two are excluded. - Test each candidate. If
n % d == 0, thennhas a divisor other than 1 and itself, so returnfalseat once. - Return
trueafter the loop. Reaching this line means the loop checked every candidate and found no divisor.
The solution in Go
func isPrime(n int) bool {
if n < 2 {
return false
}
for d := 2; d < n; d++ {
if n % d == 0 {
return false
}
}
return true
}
Go details to know:
- The three-part
for.for d := 2; d < n; d++has an initialiser, a condition and a step, separated by semicolons and with no parentheses. The variabledexists only inside the loop. %on integers. The result takes the sign of the left operand. That doesn't matter here, becausenis non-negative anddis positive, but it would matter for negative inputs.- Every path returns. The final
return trueis required. Without it, Go reportsmissing return, since the loop might finish. intis 64 bits in Go 1.22 on a 64-bit machine, so the loop counter doesn't overflow for any realistic input.
Complexity
Time: O(n). For a prime, the loop runs n - 2 times, once for each d from 2 to n - 1. For a composite number it stops at its smallest divisor, which is often much earlier. An even number above 2 ends at d = 2.
Space: O(1). Only d and n are used.
Edge cases and common mistakes
- 0 and 1. Both return
falsefrom the first check. Leaving that check out would makeisPrime(1)returntrue. - 2. It is the smallest prime. The loop starts at 2 and needs
d < 2, so it doesn't run, and the function returnstrue. - Starting the loop at 1. Every number is divisible by 1, so every input would give
false. - Ending the loop at
d <= n. Everynis divisible by itself, so that would also reject every prime. - Returning inside the loop too early. Writing
else { return true }makes the first candidate decide the answer, which is wrong: 9 is not divisible by 2 but is divisible by 3. - Perfect squares of primes. 9 and 25 are not prime. A loop that stops too early at the square root (with
<instead of<=) misses them.
Testing
isPrime(31)givestrue.isPrime(6)givesfalse.isPrime(0)andisPrime(1)givefalse.isPrime(2)givestrue.isPrime(9)givesfalse.isPrime(97)givestrue.