在问 · 算法题解

9. 回文数

简单数学反转一半数字力扣原题 ↗

题目描述

输入一个整数 x。如果把它的十进制写法从左往右读和从右往左读完全相同,它就是回文数。

x 是回文数时返回 true,否则返回 false。比如 121 是回文数,123 不是。负数带有负号,反过来读时负号在末尾,所以负数都不是回文数。

示例 1
输入:x = 121
输出:true
示例 2
输入:x = -121
输出:false

解释:反过来读是 121-,与原数不同。

示例 3
输入:x = 10
输出:false

解释:反过来读是 01,与 10 不同。

数据范围

  • -2^31 <= x <= 2^31 - 1

进阶:能否不把整数转成字符串就完成判断?

解题思路:反转一半数字

只反转后一半数字:每次把 x 的最低位搬到 rev 末尾,直到 rev >= x,此时恰好搬走了一半(奇数位时 rev 多一位中间数字)。然后比较 x == rev(偶数位)或 x == rev // 10(奇数位,去掉中间位)。末尾是 0 的正数不可能是回文,要提前排除,否则 10 会被误判。

为什么正确

循环中,x 的数字 + 反序的 rev 数字正好拼回原数;rev 是原数后半段的反转。

复杂度分析

时间 O(log x),只处理一半位数;空间 O(1)。

易错点

忘记排除末尾为 0 的数:x = 10 时 rev 变成 0 后 x = 1,会因 x == rev // 10 被误判为回文。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0 or (x % 10 == 0 and x != 0):
            return False
        rev = 0
        while x > rev:
            rev = rev * 10 + x % 10
            x //= 10
        return x == rev or x == rev // 10

载入编辑器,自己跑一遍 →

其他解法

主解法把后半段反转后与前半段比较;备选解法用除数从两端向中间双指针式比较。两者复杂度相同。

解法 2:首尾数位对比 时间 O(log x),空间 O(1)

先求出与 x 位数相同的 div=10^(位数-1),则 x/div 是最高位,x%10 是最低位。两者不等就不是回文;相等则用 (x%div)/10 同时去掉首尾两位,div 除以 100,继续比较。

直接对应「对称位置相等」的回文定义,完全不生成新数,因此不存在溢出问题。内部带 0 的情况(如 1001)依靠 div 每次除以 100 自然处理,需要想清楚才不易写错。

class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0:
            return False
        div = 1
        while x // div >= 10:
            div *= 10
        while x > 0:
            if x // div != x % 10:
                return False
            x = (x % div) // 10
            div //= 100
        return True

数学 专题的其他题目

查看 数学 全部题目 →