回文数判断的核心难点在于不使用辅助空间——必须通过数学运算(如取模、整除)逐位比较首尾数字,而非转字符串或反转整个数;需特判负数、末尾为0的数(除0外),并避免溢出与误删中间零(如1000031)。

回文数判断的核心难点在哪
关键不是“怎么写”,而是“不使用辅助空间”这个约束直接堵死了转字符串、用栈或数组存各位数字的路。必须在原数上做文章——靠数学拆解,逐位比对首尾,但不能额外开数组或字符串缓冲区。
常见错误是只反转整个数再比较(比如 reverse(x) == x),这看似没用数组,但反转过程若用 long long 存结果,本质是用了额外变量空间;更隐蔽的问题是:负数、末尾为 0 的数(除 0 外)根本不可能是回文,却常被漏判。
用数学方法逐位比对首尾数字
思路是不断取最高位和最低位对比,然后去掉这两端,继续下一轮。难点在于如何高效取最高位——不能转字符串,就得用循环除 10 找位数,再用 num / divisor 拿首位,num % 10 拿末位。
- 先特判:
x 或 <code>x % 10 == 0 && x != 0直接返回false - 用
divisor记录最高位权重(比如 1221 →divisor = 1000),通过 while 循环divisor *= 10再/= 10获得 - 每轮比较:
x / divisor(首位)和x % 10(末位),不等就返回false - 更新:
x = (x % divisor) / 10去掉首尾,divisor /= 100缩小两位权重
注意:每次 divisor 要除以 100,因为去掉了两位(首位和末位);x 先模 divisor 去首位,再除 10 去末位。
立即学习“C++免费学习笔记(深入)”;
避免整数溢出与边界细节
虽然题目要求“不使用辅助空间”,但中间计算仍可能溢出——尤其当 x 接近 INT_MAX 时,divisor 在初始化阶段反复乘 10 容易越界。安全做法是用 long 类型存 divisor,但别用它存反转结果。
-
divisor必须声明为long或long long,否则1000000000 * 10在int下直接溢出变负 - 循环找
divisor的初始值时,条件写成divisor (而非 <code>divisor ),防止 <code>divisor * 10过早溢出 - 最后一位数单独处理:当
x 且前面都匹配,就是回文;不需要再比一次
示例:对 x = 121,首轮 divisor = 100,121 / 100 == 1,121 % 10 == 1,匹配;更新后 x = (121 % 100) / 10 = 2,divisor /= 100 → 1,此时 x ,循环结束,返回 <code>true。
为什么不用反转整个数更简单
很多人第一反应是写个 reverse 函数,比如 while (x) { rev = rev * 10 + x % 10; x /= 10; },但这违反“不使用辅助空间”的隐含意图——rev 是一个与输入同量级的新整数变量,空间复杂度 O(1) 是指常数个变量,但变量值域本身不计入空间?不。严格来说,存储反转结果需要和原数相同位数的位宽,属于依赖输入规模的空间开销,只是常数因子小而已。
真正符合题意的做法,是只用固定几个变量(如 x、divisor、left、right),所有操作都在原数数值上完成,不构造任何新数字表示。
最易被忽略的是:负数和末尾零的提前退出,以及 divisor 初始化时的溢出防护——这两个点不处理,代码在 -2147483648 或 1000000009 这类边界输入上会崩或误判。


















