LeetCode 9. 回文数:不转字符串的高效解法
一、题目回顾给你一个整数x如果x是回文整数返回true否则返回false。回文数是指正序从左向右和倒序从右向左读都一样的整数。例如121是回文123不是。特殊情况负数如-121、末尾为 0 且非 0 的数如10都不是回文数。进阶要求不将整数转为字符串来解决这个问题。二、核心思路反转后半段数字如果直接反转整个整数可能会遇到溢出问题比如超过int范围。更高效的做法是先过滤掉不可能是回文数的情况负数、末尾为 0 且非 0 的数。只反转数字的后半部分和前半部分比较偶数位前半部分 反转后的后半部分 → 是回文数。奇数位前半部分 反转后的后半部分去掉最后一位 → 是回文数。三、代码实现与逐行解析bool isPalindrome(int x) { // 1. 过滤边界情况负数 或 末尾为0且非0的数不可能是回文数 if(x 0 || (x % 10 0 x ! 0)){ return false; } // 2. 反转后半段数字 int renum 0; while(x renum){ renum renum * 10 x % 10; // 把x的最后一位加到renum末尾 x / 10; // 去掉x的最后一位 } // 3. 比较前半段和反转后的后半段 return x renum || x renum / 10; }1. 边界条件过滤x 0负数带负号正读和反读一定不同 → 直接返回false。x % 10 0 x ! 0末尾为 0 且不是 0 的数如10、100首位不可能为 0 → 直接返回false。x 0是回文数此条件不触发。2. 反转后半段数字循环条件x renum保证只反转到数字的一半位置避免溢出。示例x 1221初始x 1221renum 0第 1 次循环renum 1x 122第 2 次循环renum 12x 12→ 满足x renum循环结束。3. 最终判断偶数位如1221x 12renum 12→x renum→true。奇数位如121x 1renum 12→x renum / 101 1→true。两种情况满足其一即可判定为回文数。四、复杂度分析时间复杂度O(log10n)只遍历数字的一半位数。空间复杂度O(1)仅使用常数级额外变量。优势避免了字符串转换的开销同时解决了反转整数可能导致的溢出问题。五、测试用例验证输入输出解释121true正读反读都是 121-121false负数带负号10false末尾为 0首位不为 01221true偶数位回文数0true特殊回文数六、进阶思考1. 为什么不反转整个整数如果x是INT_MAX2^31 - 1反转后会超过int范围导致溢出错误。反转后半段可以完美规避这个问题。2. 字符串解法对比如果允许转字符串实现会更直观bool isPalindrome(int x){ char s[20]; sprintf(s, %d, x); int left 0, right strlen(s) - 1; while(left right){ if(s[left] ! s[right]) return false; left; right--; } return true; }但这种方法依赖字符串操作效率略低且不符合题目进阶要求。七、总结这道题的核心是利用回文数的对称性只反转后半段数字既高效又安全。边界过滤提前排除不可能的情况减少后续计算。半段反转避免溢出同时保证时间复杂度最优。最终判断兼容偶数位和奇数位两种回文数场景。