Question:
Find the smallest prime palindrome greater than or equal to N
.
Recall that a number is prime if it's only divisors are 1 and itself, and it is greater than 1.
For example, 2,3,5,7,11 and 13 are primes.
Recall that a number is a palindrome if it reads the same from left to right as it does from right to left.
For example, 12321 is a palindrome.
1 <= N <= 10^8
- The answer is guaranteed to exist and be less than
2 * 10^8
.
求出大于或等于 N
的最小回文素数。
回顾一下,如果一个数大于 1,且其因数只有 1 和它自身,那么这个数是素数。
例如,2,3,5,7,11 以及 13 是素数。
回顾一下,如果一个数从左往右读与从右往左读是一样的,那么这个数是回文数。
例如,12321 是回文数。
1 <= N <= 10^8
- 答案肯定存在,且小于
2 * 10^8
。
分析1:求最小回文数与最小素数的结合,使用回文数判断和素数判断即可
class Solution:
def primePalindrome(self, N: int) -> int:
isPrime = False
isPalindrome = False
if N<2:
N = 2
while True:
isPrime = False
isPrime = self.JudgePrime(N)
if isPrime:
isPalindrome = self.JudgePal(N)
if isPalindrome:
return N
N += 1
def JudgePrime(self,n):
for i in range(2,int(math.sqrt(n))+1):
if n % i == 0:
return False
return True
def JudgePal(self,n):
str1 = str(n)
str2 = ''.join(reversed(str1))
if str1 == str2:
return True
return False
问题1:对数字依次进行遍历判断,耗费时间,超时示例:9989900
分析2:借鉴评论中的提示,根据如下数学规律进行优化
除 11 外的偶数位回文数,都能被 11 整除
能被 11 整数的数字特点:偶数位数字之和 = 奇数位数字之和。偶数位的回文数,偶数位的和一定等于奇数位的和,所以除了 11 其余的都不是素数。
除2外的偶数都不是素数
问题:先进行素数判断仍然耗费大量时间,超时示例:85709140
解决:将回文数判断置前以减少判断时间
class Solution:
def primePalindrome(self, N: int) -> int:
if N < 3:
return 2
elif N % 2 == 0:
N += 1
while self.JudgePal(N) == False or self.JudgePrime(N) == False:
if N > 11 and len(str(N)) % 2 == 0:
N = int(math.pow(10, len(str(N))) + 1)
else:
N += 2
return N
def JudgePrime(self, n):
for i in range(2, int(math.sqrt(n)) + 1):
if n % i == 0:
return False
return True
def JudgePal(self, n):
string = str(n)
if string == string[::-1]:
return True
return False
分析3:利用数学规律:除2、3外,素数都在6左右两侧(必为6x+1或6x-1)。相较于用偶数进行过滤,可以进一步缩小范围。
问题,n1、n2大小不一定按顺序,可能造成过多判断甚至误判,错误示例:6,输出5
解决:对n1、n2赋值后排序
class Solution:
def primePalindrome(self, N: int) -> int:
if N < 3:
return 2
elif N == 3:
return 3
if self.JudgePal(N) == False or self.JudgePrime(N) == False:
if 0 < N % 6 < 5:
n1 = N - N % 6 + 5
n2 = N - N % 6 + 7
elif N % 6 == 0:
n1 = N + 5
n2 = N + 1
elif N % 6 == 5:
n1 = N + 6
n2 = N + 2
else:
return N
if n1>n2:
n1,n2 = n2,n1
while True:
if self.Judge(n1) == False:
if n1 > 11 and len(str(n1)) % 2 == 0:
n1 = int(10 ** len(str(n2))) + 1
else:
n1 += 6
else:
return n1
if self.Judge(n2) == False:
if n2 > 11 and len(str(n2)) % 2 == 0:
n2 = int(10 ** len(str(n2))) + 1
else:
n2 += 6
else:
return n2
def Judge(self, n):
if self.JudgePal(n) == False or self.JudgePrime(n) == False:
return False
return True
def JudgePrime(self, n):
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
def JudgePal(self, n):
string = str(n)
if string == string[::-1]:
return True
return False