1952. Three Divisors
Problem Description
This problem asks you to determine whether a given integer n
has exactly three positive divisors.
A divisor of n
is any positive integer that divides n
evenly (with no remainder). For example, if n = 12
, its divisors are 1, 2, 3, 4, 6, and 12.
The task is to return true
if n
has exactly 3 divisors, and false
otherwise.
Key observations:
- Every positive integer has at least two divisors: 1 and itself
- For a number to have exactly 3 divisors, it must have exactly one additional divisor besides 1 and itself
- This only happens when
n
is a perfect square of a prime number
For example:
n = 4
has divisors {1, 2, 4} → exactly 3 divisors → returntrue
n = 9
has divisors {1, 3, 9} → exactly 3 divisors → returntrue
n = 12
has divisors {1, 2, 3, 4, 6, 12} → 6 divisors → returnfalse
The solution counts how many numbers between 2 and n-1
divide n
evenly. If exactly one such divisor exists (which would be the square root of n
if n
is a perfect square of a prime), then including 1 and n
itself gives exactly 3 total divisors.
Intuition
To understand when a number has exactly three divisors, let's think about the structure of divisors.
Every positive integer n
always has at least two divisors: 1
and n
itself. For n
to have exactly three divisors, we need exactly one more divisor.
When does this happen? Let's consider how divisors typically come in pairs. When we find a divisor d
of n
, we also get n/d
as another divisor. For instance, if 12
is divisible by 3
, then 12/3 = 4
is also a divisor. This pairing means most numbers have an even number of divisors.
The only exception is when d = n/d
, which means d² = n
. This happens when n
is a perfect square. In this case, the square root doesn't pair with another distinct divisor.
But having a perfect square isn't enough. Consider n = 16
:
- Divisors: {1, 2, 4, 8, 16}
- Even though
4² = 16
, we have 5 divisors, not 3
The key insight is that for exactly 3 divisors, we need:
- The number
1
(always present) - The number
n
itself (always present) - Exactly one number in between
This middle number must be the square root of n
, and it must be the ONLY divisor between 1
and n
. This happens when the square root is a prime number, because prime numbers have no divisors other than 1
and themselves.
Therefore, n
has exactly 3 divisors if and only if n
is the square of a prime number (like 4 = 2²
, 9 = 3²
, 25 = 5²
).
The solution cleverly counts divisors between 2
and n-1
. If this count equals 1
, then that single divisor must be the prime square root, giving us exactly 3 total divisors.
Learn more about Math patterns.
Solution Approach
The solution uses a straightforward counting approach to determine if n
has exactly three divisors.
Implementation Steps:
-
Count divisors between 2 and n-1: The solution iterates through all integers
i
from2
ton-1
and checks if each one dividesn
evenly using the modulo operator (n % i == 0
). -
Use a generator expression: The code
(n % i == 0 for i in range(2, n))
creates a generator that yieldsTrue
for each divisor found andFalse
otherwise. -
Sum the boolean values: Python treats
True
as1
andFalse
as0
, sosum()
effectively counts how many divisors exist between2
andn-1
. -
Check if count equals 1: If exactly one divisor exists in the range
[2, n-1]
, then including1
andn
itself gives exactly 3 total divisors.
Code Walkthrough:
def isThree(self, n: int) -> bool:
return sum(n % i == 0 for i in range(2, n)) == 1
range(2, n)
generates numbers from2
ton-1
n % i == 0
checks ifi
is a divisor ofn
sum(...)
counts how manyTrue
values (divisors) are found== 1
returnsTrue
if exactly one divisor exists between2
andn-1
Time Complexity: O(n)
- we check each number from 2
to n-1
Space Complexity: O(1)
- only using a constant amount of extra space
Example Trace:
- For
n = 9
: Check2, 3, 4, 5, 6, 7, 8
- Only
3
divides9
evenly - Count = 1, so return
True
- Only
- For
n = 12
: Check2, 3, 4, 5, 6, 7, 8, 9, 10, 11
2, 3, 4, 6
all divide12
evenly- Count = 4, so return
False
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with n = 9
:
Step 1: Identify what we're looking for
- We need to check if 9 has exactly 3 divisors total
- We know 1 and 9 are always divisors, so we need exactly 1 more
Step 2: Check each potential divisor from 2 to 8
i = 2
: Is 9 % 2 == 0? No (9 ÷ 2 = 4 remainder 1) → Not a divisori = 3
: Is 9 % 3 == 0? Yes (9 ÷ 3 = 3 remainder 0) → Found a divisor!i = 4
: Is 9 % 4 == 0? No (9 ÷ 4 = 2 remainder 1) → Not a divisori = 5
: Is 9 % 5 == 0? No (9 ÷ 5 = 1 remainder 4) → Not a divisori = 6
: Is 9 % 6 == 0? No (9 ÷ 6 = 1 remainder 3) → Not a divisori = 7
: Is 9 % 7 == 0? No (9 ÷ 7 = 1 remainder 2) → Not a divisori = 8
: Is 9 % 8 == 0? No (9 ÷ 8 = 1 remainder 1) → Not a divisor
Step 3: Count the divisors found
- We found exactly 1 divisor (the number 3) in the range [2, 8]
Step 4: Determine the result
- Since we found exactly 1 divisor between 2 and n-1, the total divisors are:
- 1 (always a divisor)
- 3 (the one we found)
- 9 (n itself, always a divisor)
- Total: 3 divisors → Return
true
Why this works: The number 9 = 3², where 3 is prime. Prime squares always have exactly 3 divisors: 1, the prime number itself, and the square.
Solution Implementation
1class Solution:
2 def isThree(self, n: int) -> bool:
3 """
4 Determines if a number has exactly three divisors.
5
6 A number has exactly three divisors if and only if it's the square of a prime.
7 For example: 4 has divisors [1, 2, 4], 9 has divisors [1, 3, 9].
8
9 Args:
10 n: A positive integer to check.
11
12 Returns:
13 True if n has exactly three divisors, False otherwise.
14 """
15 # Count divisors in range [2, n-1]
16 # If exactly one divisor exists in this range, then with 1 and n itself,
17 # the total number of divisors is 3
18 divisor_count = sum(n % i == 0 for i in range(2, n))
19
20 # Check if there's exactly one divisor between 2 and n-1
21 return divisor_count == 1
22
1class Solution {
2 /**
3 * Determines if a positive integer has exactly three divisors.
4 * A number has exactly three divisors if and only if it is the square of a prime number.
5 * For example: 4 has divisors [1, 2, 4], and 9 has divisors [1, 3, 9].
6 *
7 * @param n the positive integer to check
8 * @return true if n has exactly three divisors, false otherwise
9 */
10 public boolean isThree(int n) {
11 // Count the number of divisors between 2 and n-1 (exclusive of 1 and n)
12 int divisorCount = 0;
13
14 // Check each potential divisor from 2 to n-1
15 for (int i = 2; i < n; i++) {
16 // If i divides n evenly, it's a divisor
17 if (n % i == 0) {
18 divisorCount++;
19 }
20 }
21
22 // A number has exactly 3 divisors when it has exactly 1 divisor
23 // between 2 and n-1 (since 1 and n are always divisors)
24 return divisorCount == 1;
25 }
26}
27
1class Solution {
2public:
3 /**
4 * Determines if a number has exactly three divisors.
5 * A number has exactly three divisors if and only if it's a perfect square of a prime number.
6 * For example: 4 = 2^2 has divisors {1, 2, 4}, 9 = 3^2 has divisors {1, 3, 9}.
7 *
8 * @param n The number to check
9 * @return true if n has exactly three divisors, false otherwise
10 */
11 bool isThree(int n) {
12 // Count divisors between 2 and n-1 (excluding 1 and n itself)
13 int divisorCount = 0;
14
15 // Check all potential divisors from 2 to n-1
16 for (int i = 2; i < n; ++i) {
17 // If i divides n evenly, increment the count
18 if (n % i == 0) {
19 divisorCount++;
20 }
21 }
22
23 // A number has exactly 3 divisors when it has exactly 1 divisor
24 // between 2 and n-1 (since 1 and n are always divisors)
25 return divisorCount == 1;
26 }
27};
28
1/**
2 * Determines if a number has exactly three divisors.
3 * A number has exactly three divisors if and only if it is the square of a prime number.
4 * For example: 4 has divisors [1, 2, 4], 9 has divisors [1, 3, 9].
5 *
6 * @param n - The number to check
7 * @returns true if n has exactly three divisors, false otherwise
8 */
9function isThree(n: number): boolean {
10 // Count the number of divisors between 2 and n-1 (exclusive of 1 and n)
11 let divisorCount: number = 0;
12
13 // Check each potential divisor from 2 to n-1
14 for (let i: number = 2; i < n; ++i) {
15 // If i divides n evenly, it's a divisor
16 if (n % i === 0) {
17 ++divisorCount;
18 }
19 }
20
21 // A number has exactly 3 divisors when it has exactly 1 divisor
22 // between 2 and n-1 (plus 1 and n itself makes 3 total)
23 return divisorCount === 1;
24}
25
Time and Space Complexity
Time Complexity: O(n)
The code iterates through all integers from 2 to n-1 (using range(2, n)
), checking if each number is a divisor of n by computing n % i == 0
. This results in n - 2
iterations, making the time complexity linear with respect to n.
Space Complexity: O(1)
The generator expression (n % i == 0 for i in range(2, n))
is evaluated lazily and consumed immediately by the sum()
function. No additional data structures are created to store intermediate results. The only space used is for the loop variable i
and the accumulator in sum()
, both of which require constant space regardless of the input size.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Inefficient Time Complexity for Large Values
The current solution has O(n) time complexity, which becomes extremely slow for large values of n. For example, if n = 10^9, the algorithm would need to check nearly a billion numbers.
Problem Example:
# This would be very slow for large n
def isThree(self, n: int) -> bool:
return sum(n % i == 0 for i in range(2, n)) == 1
Solution: Optimize by only checking up to √n, since divisors come in pairs:
def isThree(self, n: int) -> bool:
if n < 4:
return False
# Check if n is a perfect square
sqrt_n = int(n ** 0.5)
if sqrt_n * sqrt_n != n:
return False
# Check if the square root is prime
if sqrt_n < 2:
return False
for i in range(2, int(sqrt_n ** 0.5) + 1):
if sqrt_n % i == 0:
return False
return True
2. Edge Case: Small Values of n
The original solution doesn't explicitly handle edge cases where n < 4, though it works correctly due to the logic.
Problem Example:
# For n = 1: divisors are [1] → only 1 divisor # For n = 2: divisors are [1, 2] → only 2 divisors # For n = 3: divisors are [1, 3] → only 2 divisors
Solution: Add explicit edge case handling for clarity:
def isThree(self, n: int) -> bool:
if n < 4: # Numbers less than 4 cannot have exactly 3 divisors
return False
return sum(n % i == 0 for i in range(2, n)) == 1
3. Mathematical Understanding Gap
Not recognizing that only perfect squares of prime numbers have exactly 3 divisors can lead to inefficient brute-force solutions.
Why this matters:
- Perfect square of prime p: divisors are [1, p, p²]
- Any other number will have either 2 divisors (prime), 4+ divisors (composite), or an even number of divisors (non-perfect squares)
Optimized Solution Using This Property:
def isThree(self, n: int) -> bool:
# Check if n is a perfect square
sqrt_n = int(n ** 0.5)
if sqrt_n * sqrt_n != n:
return False
# Check if sqrt_n is prime
if sqrt_n <= 1:
return False
if sqrt_n == 2:
return True
if sqrt_n % 2 == 0:
return False
# Check odd divisors only
for i in range(3, int(sqrt_n ** 0.5) + 1, 2):
if sqrt_n % i == 0:
return False
return True
4. Integer Overflow/Precision Issues
When checking if n is a perfect square using floating-point arithmetic, precision errors might occur for very large numbers.
Problem Example:
# Potential precision issue
sqrt_n = n ** 0.5
if int(sqrt_n) ** 2 == n: # May fail for large n due to float precision
Solution: Use integer-only arithmetic:
def isThree(self, n: int) -> bool:
# Binary search for perfect square check (avoids float precision issues)
left, right = 1, n
while left <= right:
mid = (left + right) // 2
square = mid * mid
if square == n:
# Check if mid is prime
return self.isPrime(mid)
elif square < n:
left = mid + 1
else:
right = mid - 1
return False
def isPrime(self, num: int) -> bool:
if num < 2:
return False
for i in range(2, int(num ** 0.5) + 1):
if num % i == 0:
return False
return True
You are given an array of intervals where intervals[i] = [start_i, end_i]
represent the start and end of the ith
interval. You need to merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!