3765. Complete Prime Number
Problem Description
You are given an integer num.
A number num is called a Complete Prime Number if every prefix and every suffix of num is prime.
Your task is to return true if num is a Complete Prime Number, otherwise return false.
Here are some important points to understand:
- A prefix of a number is formed by taking the first
kdigits of the number. For example, the prefixes of233are2,23, and233. - A suffix of a number is formed by taking the last
kdigits of the number. For example, the suffixes of233are3,33, and233. - A single-digit number is considered a Complete Prime Number only if the digit itself is prime (that is,
2,3,5, or7).
In short, you need to check all prefixes and all suffixes of num. The number qualifies as a Complete Prime Number only when every one of these values is prime.
How We Pick the Algorithm
Why Number Theory?
This problem maps to Number Theory through a short path in the full flowchart.
Checking whether every prefix and suffix of a number is prime involves primality testing, a classic number theory operation.
Open in FlowchartIntuition
The problem asks us to verify a condition over every prefix and every suffix of num. This naturally breaks the task into two independent checks: one for all prefixes and one for all suffixes. If both checks pass, the number is a Complete Prime Number.
The first thing we need is a way to test whether a single number is prime. A number x is prime if it has no divisors other than 1 and itself. Instead of checking every integer up to x, we only need to check divisors from 2 up to sqrt(x). This is because if x has a divisor larger than sqrt(x), it must also have a matching divisor smaller than sqrt(x), so we would have already found it. This gives us an efficient is_prime helper.
Next, we need to generate all the prefixes and suffixes. The cleanest way to handle the digits is to convert num into a string s. Once we have the string, we can build the numeric values step by step:
-
For prefixes, we read the digits from left to right. Starting from
0, each time we see a new digitc, we update our value asx = x * 10 + int(c). This grows the number one digit at a time, naturally producing2, then23, then233, and so on. -
For suffixes, we read the digits from right to left. We keep a place value
p(which starts at1and multiplies by10each step) and updatex = p * int(c) + x. This builds the suffix values from the last digit inward, producing3, then33, then233.
The key insight is that by constructing these numbers incrementally, we avoid repeatedly slicing the string and re-parsing it. As soon as any prefix or suffix turns out to be not prime, we can immediately return false, since the Complete Prime condition requires all of them to be prime. If we finish both loops without finding a non-prime value, we return true.
Pattern Learn more about Math patterns.
Solution Approach
We follow a Mathematics-based approach, combining a primality test with incremental number construction.
Step 1: The primality test
We define a helper function is_prime(x) to determine whether a number x is prime:
- If
x < 2, thenxis not prime, so we returnFalse. - Otherwise, we check every integer
iin the range from2toint(sqrt(x)) + 1. If anyidividesxevenly (that is,x % i == 0), thenxis not prime. In the code,all(x % i for i in range(2, int(sqrt(x)) + 1))returnsTrueonly when none of the values in that range dividex, meaningxis prime.
Checking up to sqrt(x) is sufficient because any factor larger than sqrt(x) must pair with a factor smaller than sqrt(x).
Step 2: Convert the number to a string
We convert num into a string s using s = str(num). This lets us access each digit easily and process them in order.
Step 3: Check all prefixes (left to right)
We initialize x = 0. Then we iterate over each character c in s from left to right:
- Update the prefix value with
x = x * 10 + int(c). This appends the new digit to the end of the current number, growing the prefix one digit at a time. - Call
is_prime(x). If it returnsFalse, we immediately returnFalse, because a non-prime prefix disqualifiesnum.
Step 4: Check all suffixes (right to left)
We reset x = 0 and introduce a place value p = 1. Then we iterate over each character c in the reversed string s[::-1]:
- Update the suffix value with
x = p * int(c) + x. Hereprepresents the positional weight (1,10,100, ...) of the current digit, so we place the new digit in front of the existing suffix. - Multiply
pby10withp *= 10to prepare for the next digit. - Call
is_prime(x). If it returnsFalse, we returnFalseright away.
Step 5: Final result
If both loops complete without finding any non-prime prefix or suffix, every prefix and suffix is prime, so we return True.
Complexity Analysis
Let n be the number of digits in num, and let M be the value of num itself.
- Time complexity: There are
O(n)prefixes andO(n)suffixes. For each, the primality check costsO(sqrt(M)). Thus the overall time isO(n * sqrt(M)). - Space complexity:
O(n)for storing the string representations, while the incremental construction uses only a constant amount of extra space.
Example Walkthrough
Let's trace through the solution approach using a small example: num = 233.
Setup: Convert to string
We start by converting the number into a string so we can process each digit:
s = "233"
Step 1: Check all prefixes (left to right)
We initialize x = 0 and read the digits from left to right, building each prefix incrementally with x = x * 10 + int(c).
Digit c | Computation x = x * 10 + int(c) | Prefix value x | is_prime(x)? |
|---|---|---|---|
2 | 0 * 10 + 2 | 2 | ✅ prime |
3 | 2 * 10 + 3 | 23 | ✅ prime |
3 | 23 * 10 + 3 | 233 | ✅ prime |
Let's verify one primality check in detail. For x = 23, we test divisors from 2 up to int(sqrt(23)) + 1 = 5:
23 % 2 = 1(not divisible)23 % 3 = 2(not divisible)23 % 4 = 3(not divisible)
No divisor is found, so 23 is prime. ✅
All prefixes (2, 23, 233) are prime, so we do not return false here and proceed to the suffixes.
Step 2: Check all suffixes (right to left)
We reset x = 0 and introduce the place value p = 1. We read the digits from right to left over s[::-1] = "332", building each suffix with x = p * int(c) + x, then updating p *= 10.
Digit c | Place p | Computation x = p * int(c) + x | Suffix value x | is_prime(x)? | New p |
|---|---|---|---|---|---|
3 | 1 | 1 * 3 + 0 | 3 | ✅ prime | 10 |
3 | 10 | 10 * 3 + 3 | 33 | ❌ not prime | 100 |
When we reach the suffix 33, the primality check fails. Testing divisors from 2 to int(sqrt(33)) + 1 = 6:
33 % 3 = 0(divisible!)
Since 33 = 3 * 11, it is not prime. The moment is_prime(33) returns False, we immediately return false without examining the remaining suffix 233.
Result
num = 233 is not a Complete Prime Number, so the function returns false. Even though every prefix was prime, the suffix 33 broke the condition, which demonstrates why both checks are required.
A passing example for contrast: num = 23
To see a true result, consider num = 23:
- Prefixes:
2(prime ✅),23(prime ✅) - Suffixes:
3(prime ✅),23(prime ✅)
Every prefix and every suffix is prime, so both loops complete without returning early, and the function returns true. This shows the case where all incremental constructions pass the primality test and the final return True is reached.
Solution Implementation
1from math import isqrt
2
3
4class Solution:
5 def completePrime(self, num: int) -> bool:
6 # Helper that checks whether a single integer is prime.
7 def is_prime(value: int) -> bool:
8 if value < 2:
9 return False
10 # Test divisibility only up to the integer square root of value.
11 # all(...) returns False as soon as a divisor is found.
12 return all(value % divisor for divisor in range(2, isqrt(value) + 1))
13
14 digits = str(num)
15
16 # Check every prefix: build the number digit by digit from the left.
17 # e.g. for "239" -> 2, 23, 239
18 prefix = 0
19 for char in digits:
20 prefix = prefix * 10 + int(char)
21 if not is_prime(prefix):
22 return False
23
24 # Check every suffix: build the number digit by digit from the right.
25 # e.g. for "239" -> 9, 39, 239
26 suffix, place_value = 0, 1
27 for char in reversed(digits):
28 suffix = place_value * int(char) + suffix
29 place_value *= 10
30 if not is_prime(suffix):
31 return False
32
33 # All prefixes and suffixes are prime.
34 return True
351class Solution {
2 /**
3 * Determines whether the given number is a "complete prime".
4 * A number qualifies only if:
5 * 1. Every prefix (read left to right) is prime.
6 * 2. Every suffix (read left to right within the number) is prime.
7 *
8 * @param num the number to validate
9 * @return true if all prefixes and suffixes are prime, false otherwise
10 */
11 public boolean completePrime(int num) {
12 // Convert the number into its individual digit characters.
13 char[] digits = String.valueOf(num).toCharArray();
14
15 // ---- Check every prefix (built from left to right). ----
16 int prefixValue = 0;
17 for (int i = 0; i < digits.length; i++) {
18 // Append the current digit to the growing prefix.
19 prefixValue = prefixValue * 10 + (digits[i] - '0');
20 // If any prefix is not prime, the number fails immediately.
21 if (!isPrime(prefixValue)) {
22 return false;
23 }
24 }
25
26 // ---- Check every suffix (built from right to left). ----
27 int suffixValue = 0;
28 int placeValue = 1; // Tracks the positional weight (1, 10, 100, ...).
29 for (int i = digits.length - 1; i >= 0; i--) {
30 // Add the current digit at its correct positional weight.
31 suffixValue = placeValue * (digits[i] - '0') + suffixValue;
32 placeValue *= 10;
33 // If any suffix is not prime, the number fails immediately.
34 if (!isPrime(suffixValue)) {
35 return false;
36 }
37 }
38
39 // All prefixes and suffixes are prime.
40 return true;
41 }
42
43 /**
44 * Checks whether a given value is a prime number.
45 *
46 * @param value the value to test
47 * @return true if value is prime, false otherwise
48 */
49 private boolean isPrime(int value) {
50 // Numbers less than 2 are not prime by definition.
51 if (value < 2) {
52 return false;
53 }
54 // Test divisibility up to the square root of value.
55 for (int i = 2; i * i <= value; i++) {
56 if (value % i == 0) {
57 return false;
58 }
59 }
60 return true;
61 }
62}
631class Solution {
2public:
3 bool completePrime(int num) {
4 // Helper lambda to check whether a given value is a prime number.
5 auto isPrime = [&](int value) {
6 // Any number less than 2 is not prime.
7 if (value < 2) {
8 return false;
9 }
10 // Trial division up to sqrt(value) to detect factors.
11 for (int i = 2; i * i <= value; ++i) {
12 if (value % i == 0) {
13 return false;
14 }
15 }
16 return true;
17 };
18
19 // Convert the number to its string representation for digit-wise processing.
20 string digits = to_string(num);
21
22 // Check every prefix (left-to-right) of the number for primality.
23 int prefix = 0;
24 for (char c : digits) {
25 // Append the current digit to build the next prefix value.
26 prefix = prefix * 10 + (c - '0');
27 if (!isPrime(prefix)) {
28 return false;
29 }
30 }
31
32 // Check every suffix (right-to-left) of the number for primality.
33 int suffix = 0;
34 int placeValue = 1;
35 for (int i = (int) digits.size() - 1; i >= 0; --i) {
36 // Prepend the current digit using the running place value.
37 suffix = placeValue * (digits[i] - '0') + suffix;
38 placeValue *= 10;
39 if (!isPrime(suffix)) {
40 return false;
41 }
42 }
43
44 // All prefixes and suffixes are prime, so the number is a "complete prime".
45 return true;
46 }
47};
481/**
2 * Determines whether a number is a "complete prime", meaning every prefix
3 * (read left-to-right) and every suffix (read right-to-left) of the number is prime.
4 *
5 * @param num - The number to evaluate.
6 * @returns True if all prefixes and suffixes are prime, otherwise false.
7 */
8function completePrime(num: number): boolean {
9 /**
10 * Checks whether a given value is a prime number.
11 *
12 * @param value - The candidate number to test for primality.
13 * @returns True if the value is prime, otherwise false.
14 */
15 const isPrime = (value: number): boolean => {
16 // Any value below 2 cannot be prime.
17 if (value < 2) {
18 return false;
19 }
20 // Trial division up to the square root of the value.
21 for (let divisor = 2; divisor * divisor <= value; divisor++) {
22 if (value % divisor === 0) {
23 return false;
24 }
25 }
26 return true;
27 };
28
29 // Convert the number to its string representation to iterate over digits.
30 const digits = String(num);
31
32 // ----- Check every prefix (left to right) -----
33 let prefixValue = 0;
34 for (let i = 0; i < digits.length; i++) {
35 // Append the current digit to the accumulated prefix value.
36 // (charCodeAt - 48) converts the character to its numeric value.
37 prefixValue = prefixValue * 10 + (digits.charCodeAt(i) - 48);
38 if (!isPrime(prefixValue)) {
39 return false;
40 }
41 }
42
43 // ----- Check every suffix (right to left) -----
44 let suffixValue = 0;
45 let placeValue = 1; // Tracks the current digit's positional weight (1, 10, 100, ...).
46 for (let i = digits.length - 1; i >= 0; i--) {
47 // Add the current digit, scaled by its place value, to the suffix.
48 suffixValue = placeValue * (digits.charCodeAt(i) - 48) + suffixValue;
49 placeValue *= 10;
50 if (!isPrime(suffixValue)) {
51 return false;
52 }
53 }
54
55 // All prefixes and suffixes are prime.
56 return true;
57}
58Time and Space Complexity
-
Time complexity:
O(sqrt(n) × log n). Letnbe the value of the integernum, so the number of digits innumisO(log n). The code processes the digits in two passes (the prefixes from left to right and the suffixes from right to left), each pass iteratingO(log n)times. In every iteration, the functionis_prime(x)is called, and sincexis bounded byn, each primality check costsO(sqrt(x)) = O(sqrt(n)). Therefore the overall time complexity isO(log n × sqrt(n)) = O(sqrt(n) × log n). -
Space complexity:
O(log n). The strings = str(num)stores all digits ofnum, which requiresO(log n)space. Therangeinis_primeis a lazy iterator underall, consuming onlyO(1)additional space, and the remaining variables (x,p) also useO(1)space. Thus the dominant term is the string storage, givingO(log n).
Pattern Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Mishandling suffixes that contain leading zeros
The most common mistake is treating a suffix purely as a numeric value while ignoring the meaning of leading zeros. When a digit 0 appears in the middle of num, the suffix that starts at that 0 will have a leading zero.
For example, consider num = 307:
- Suffixes (as strings) are
"7","07", and"307". - If you naively convert
"07"to an integer, you get7, which is prime, so the suffix check silently passes.
But conceptually "07" is not a valid 2-digit prime — it has a leading zero. Depending on how the problem defines a "suffix," collapsing "07" into 7 can produce a false positive. The incremental construction in the code does exactly this collapse:
suffix = place_value * int(char) + suffix # "07" becomes 0*10 + 7 = 7
Solution: Decide explicitly whether a leading-zero suffix is allowed. If it is not, reject any suffix whose leading digit is 0 (except the single digit 0 itself, which is not prime anyway):
suffix, place_value = 0, 1
for char in reversed(digits):
if char == '0' and place_value > 1:
# A multi-digit suffix starting with '0' is invalid.
return False
suffix = place_value * int(char) + suffix
place_value *= 10
if not is_prime(suffix):
return False
This guarantees that a value like 307 is correctly rejected, because the suffix "07" is recognized as malformed rather than being silently reduced to a prime.
Pitfall 2: Inefficient primality testing for large numbers
The primality check runs in O(sqrt(M)), where M is the value of the largest prefix/suffix (essentially num itself). For numbers with many digits, M grows exponentially with the digit count n, so sqrt(M) becomes very large and the trial-division test becomes a bottleneck.
Solution: Use a faster deterministic primality test, such as the Miller–Rabin test, which runs in roughly O(log³ M) time with a fixed set of witnesses that is provably correct for all 64-bit integers:
def is_prime(n: int) -> bool:
if n < 2:
return False
for p in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37):
if n % p == 0:
return n == p
d, r = n - 1, 0
while d % 2 == 0:
d //= 2
r += 1
for a in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37):
x = pow(a, d, n)
if x == 1 or x == n - 1:
continue
for _ in range(r - 1):
x = x * x % n
if x == n - 1:
break
else:
return False
return True
This keeps performance stable even when num has many digits.
Pitfall 3: Redundant work between prefix and suffix checks
The full number num is both the longest prefix and the longest suffix, so is_prime(num) is computed twice. For a single call this is harmless, but if completePrime is invoked many times (or num is large), the repeated work adds up.
Solution: Compute the primality of the full number once and reuse it, or simply note that if the longest prefix already failed, the suffix loop is never reached. A small early-exit optimization is to check the full number first:
if not is_prime(num): return False
This prunes most non-qualifying inputs immediately before doing any per-digit work.
Ready to land your dream job?
Unlock your dream job with a 5-minute quiz for a personalized study roadmap!
Get My RoadmapHow does merge sort divide the problem into subproblems?
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 If you prefer videos here's a video that explains recursion in a fun and easy way 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 him
Want a Structured Path to Master System Design Too? Don’t Miss This!