回文数判断核心是反转整数后比较相等,需先排除负数和末尾为0的非零数;用long long防溢出,再逐位反转并比对。

用整数反转法判断回文数的核心逻辑
直接反转原数字再比较是否相等,是不转字符串时最稳妥的思路。关键在于:反转过程必须避免溢出,且要处理末尾为 0 的非零数(如 10)——这类数不可能是回文,应提前返回 false。
反转时用 long long 存储反转结果,能覆盖 int 范围内所有可能的反转值(例如 INT_MAX = 2147483647 反转后是 7463847412,已超 int,但仍在 long long 内)。
示例逻辑:
bool isPalindrome(int x) {
if (x < 0 || (x % 10 == 0 && x != 0)) return false;
long long rev = 0;
int tmp = x;
while (tmp) {
rev = rev * 10 + tmp % 10;
tmp /= 10;
}
return rev == x;
}为什么不能只反转一半数字
反转一半看似高效(比如 1221 → 反转得 12,原数剩 12),但边界条件极难处理:奇数位数时中间那位要不要丢、如何安全截断、负数和末尾零的判断仍需前置逻辑。
立即学习“C++免费学习笔记(深入)”;
实际编码中,仅反转一半带来的性能提升微乎其微(现代 CPU 对几十次除法取模几乎无感),却显著增加出错概率。常见翻车点包括:
-
1001处理中漏判x % 10 == 0导致进入循环,反转一半后得到10和10,误判为回文 - 用
int存反转一半结果,遇到1999999999类数字时反转部分溢出,行为未定义 - 奇偶位数统一用
rev > x作终止条件,但x == 0或x本身是单数字时逻辑错乱
负数和末尾零必须单独拦截
负号天然破坏回文结构,所以所有 x 直接返回 <code>false。而末尾零的数(如 120)反转后是 21,与原数不等,但如果不提前拦截 x % 10 == 0 && x != 0,就会让 0 本身通过(0 是回文),同时把 10、200 等错误放行。
这个判断必须放在反转前,否则:
-
10进入循环 →rev = 0*10 + 10%10 = 0→tmp = 1→ 继续 →rev = 0*10 + 1%10 = 1→ 最终rev == 1,x == 10,比较失败,虽结果正确但多做了无效计算 - 更糟的是,若用反转一半逻辑,
10可能被截成1和0,比较时变成1 == 0,漏掉错误
注意整型溢出与类型隐式转换
即使你声明 long long rev,如果写成 rev = rev * 10 + tmp % 10 且 rev 当前值极大(如接近 LLONG_MAX / 10),乘法仍可能先溢出再赋值,导致未定义行为。不过对 int 输入来说,最大反转值是 7463847412(2147483647 反转),远小于 LLONG_MAX(通常为 9223372036854775807),所以此处安全。
真正容易忽略的是:若把函数参数改成 long long x,就无法再用 long long 安全反转(因为 LLONG_MIN 反转后可能溢出)。此时必须改用字符串或数学分段法——但题目限定“不使用字符串”,那就得接受该解法仅适用于 int 范围输入。
也就是说,这个解法的隐含前提其实是:x 是 int 类型且在平台 INT_MIN~INT_MAX 范围内。超出此范围的输入,需要额外校验或换策略。


















