题目描述
求出大于或等于 N 的最小回文素数。
如果一个数大于 1,且其因数只有 1 和它自身,那么这个数是素数。 例如,2,3,5,7,11 以及 13 是素数。
如果一个数从左往右读与从右往左读是一样的,那么这个数是回文数,例如,12321 是回文数。
输入描述
一个数
输出描述
一个数
**示例1
输入
6
输出
7
说明
**示例2
输入
8
输出
11
思路
- 枚举:从N开始逐个遍历整数,保证找“最小”;
- 双校验:
- 回文数:字符串反转后与原串对比或用双指针判断;
- 素数:基于定理(仅验到√n,跳过偶数)判定;
- 终止:找到首个同时满足的数即输出。
核心优化
- 素数校验:范围缩至√n,仅验奇数;
- 枚举:跳过大于2的偶数,减少无效遍历。
代码
function solution() {
// 读取输入的数字N,目标是找到≥N的最小回文素数
const N = Number(readline());
/**
* 判断一个数是否是回文数
* 回文数定义:从左到右读和从右到左读完全一致的数
* @param {number} n - 待判断的数字
* @returns {boolean} 是回文数返回true,否则返回false
*/
function isPalindrome(n) {
const s = n.toString(); // 转为字符串便于反转对比
// 反转字符串:split拆分为数组→reverse反转→join还原为字符串,与原字符串对比
return s === s.split('').reverse().join('');
}
/**
* 判断一个数是否是素数(核心逻辑,含素数定理和多重优化)
* 素数定义:大于1,且只能被1和自身整除的自然数
* 素数判断核心定理:
* 1. 若数n有大于√n的因数,则必然存在一个对应的小于√n的因数,因此只需校验到√n即可
* 2. 除2外,所有偶数都不是素数;除3外,所有3的倍数都不是素数(此处仅优化偶数)
* @param {number} n - 待判断的数字
* @returns {boolean} 是素数返回true,否则返回false
*/
function isPrime(n) {
// 边界1:≤1的数不是素数
if (n <= 1) return false;
// 边界2:2是唯一的偶素数,直接返回true
if (n === 2) return true;
// 优化1:大于2的偶数必然不是素数,直接排除(减少50%的校验量)
if (n % 2 === 0) return false;
// 优化2:仅校验奇数,且只需校验到√n(用i*i ≤n替代Math.sqrt(n),避免浮点精度误差)
// 起始值为3(已排除偶数),步长为2(只遍历奇数)
for (let i = 3; i * i <= n; i += 2) {
// 若能被整除,说明存在1和自身外的因数,不是素数
if (n % i === 0) {
return false;
}
}
// 所有校验通过,是素数
return true;
}
// 从N开始枚举,寻找第一个满足“回文数+素数”的数
let num = N;
while (true) {
// 同时满足回文数和素数,即为目标值,输出并终止程序
if (isPalindrome(num) && isPrime(num)) {
console.log(num);
return;
}
num++; // 不满足则枚举下一个数
// 额外优化:跳过大于2的偶数(减少无效枚举,与isPrime中的偶数判断形成双重优化)
if (num > 2 && num % 2 === 0) {
num++;
}
}
}
// 测试用例
const cases = [
`6`,
`8`
];
let caseIndex = 0, lineIndex = 0;
const readline = (() => {
let lines = [];
return () => {
if (!lineIndex) lines = cases[caseIndex].trim().split('\n').map(l => l.trim());
return lines[lineIndex++];
};
})();
cases.forEach((_, i) => {
caseIndex = i;
lineIndex = 0;
solution();
console.log('-------');
});
767

被折叠的 条评论
为什么被折叠?



