Taro Logo

Prime Palindrome

Medium
Google logo
Google
2 views
Topics:
ArraysStringsTwo Pointers

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.

  • For example, 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.

  • For example, 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:

  1. Small numbers (n < 10)
  2. Large numbers (n close to 108)
  3. Even length palindromes.

Solution


Naive Approach

The most straightforward approach is to iterate through numbers starting from n and check each number for two conditions:

  1. Is it a palindrome?
  2. Is it a prime number?

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
  • Time Complexity: In the worst case, we might have to check many numbers. The 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.
  • Space Complexity: O(1), as we're only using a constant amount of extra space.

Optimal Approach

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.

  1. Generate odd-length palindromes.
  2. Check if the generated palindrome is greater than or equal to n.
  3. Check if it's prime.
  4. If both conditions are true, return the palindrome.
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
  • Time Complexity: Generating palindromes is more efficient. The 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.
  • Space Complexity: O(1) or O(log n), depending on the implementation details. The space used is for storing the generated palindrome, which has a length proportional to log n, or a constant number of variables in the is_prime.

Edge Cases

  1. Small Numbers: Numbers less than 10 should be handled explicitly (2, 3, 5, 7, 11).
  2. Even Length Palindromes: As mentioned, all even-length palindromes are divisible by 11, so we only need to check 11 and can skip generating other even-length palindromes greater than 11.
  3. Input Range: The problem statement specifies the range is [1, 108]. The generated palindrome should be within the range [2, 2 * 108].