Given an integer n
, return the smallest prime palindrome greater than or equal to n
.
An integer is prime if it has exactly two divisors: 1
and itself. Note that 1
is not a prime number.
2
, 3
, 5
, 7
, 11
, and 13
are all primes.An integer is a palindrome if it reads the same from left to right as it does from right to left.
101
and 12321
are palindromes.Example 1:
Input: n = 6
Output: 7
Example 2:
Input: n = 8
Output: 11
Example 3:
Input: n = 13
Output: 101
Write a function to solve this problem with optimal time and space complexity. Consider edge cases such as:
The most straightforward approach is to iterate through numbers starting from n
and check each number for two conditions:
If both conditions are met, we return that number. This is a brute-force approach.
def is_palindrome(n):
s = str(n)
return s == s[::-1]
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
def prime_palindrome(n):
num = n
while True:
if is_palindrome(num) and is_prime(num):
return num
num += 1
is_prime
function has a time complexity of O(sqrt(n)), and the is_palindrome
check is O(k) where k is the number of digits, which is approximately O(log n). The outer loop could iterate an arbitrary number of times. Therefore, the overall time complexity is difficult to precisely determine but could be substantial in the worst-case scenario.Since we're looking for a prime palindrome, we can generate palindromes and then check if they are prime. This is more efficient because palindromes have a specific structure that we can exploit.
Also, the problem statement constrains the input to be less than 108. The next largest palindrome after 99,999,999 is 100,000,001. So, we can generate palindromes up to 2 * 108, but we can make some observations to reduce the search space.
Consider that all even-length palindromes are divisible by 11, and therefore not prime (except for 11 itself). Therefore, after the single-digit primes, we only need to consider odd-length palindromes.
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
def generate_palindrome(length):
if length == 1:
yield from [2, 3, 5, 7, 11] # Handle single and double digit primes.
return
half_length = (length + 1) // 2
for i in range(10**(half_length - 1), 10**half_length):
s = str(i)
palindrome = s + s[:half_length - (length % 2)][::-1]
yield int(palindrome)
def prime_palindrome(n):
length = len(str(n))
#Ensure length is odd, unless its a small number
if length % 2 == 0 and n > 11:
length += 1
for l in range(len(str(n)), 9): #Limit search range to avoid overflow issues
for palindrome in generate_palindrome(l):
if palindrome >= n and is_prime(palindrome):
return palindrome
return None # Or raise an exception if no solution is found within the range
is_prime
check remains O(sqrt(n)). However, since we only generate palindromes, the outer loop iterates a smaller number of times. The number of palindromes generated significantly reduces the search space, making this approach much faster.11
and can skip generating other even-length palindromes greater than 11.