【每日一题】LeetCode - 判断回文数

今天我们来看一道经典的回文数题目,给定一个整数 x ,判断它是否是回文整数。如果 x 是一个回文数,则返回 true,否则返回 false
回文数 是指从左往右读和从右往左读都相同的整数。例如,121 是回文,而 123 不是。

示例

  • 示例 1

    输入:x = 121

    输出:true

    解释:121 从左往右和从右往左都相同,因此是回文数。

  • 示例 2

    输入:x = -121

    输出:false

    解释:从左向右读为 -121,从右向左读为 121-。负号出现在末尾,因此不是回文数。

  • 示例 3

    输入:x = 10

    输出:false

    解释:从右向左读为 01,与原数不相同。


思路解析

本题的核心是判断一个数字在正序和倒序上是否一致。一般地,可以想到两种解决方案:

  1. 字符串法:将整数转为字符串,判断字符串是否为回文。虽然这种方法简单直观,但它占用额外空间,不是最优解。

  2. 数学反转法:直接在数字层面反转整数的一半,再与另一半比较。这个方法通过操作数字本身,不使用额外空间,效率较高且实现优雅。

接下来,我们基于数学反转法优化解答。


优化的数学反转解法

在反转整数时,不需要整个数字的倒序,只需反转其一半。在反转过程中,如果反转后的数字与剩余的部分一致,说明该数字是回文。

优化步骤

  1. 负数直接排除:负数不可能是回文,因为其倒序会使负号出现在末尾。

  2. 非零且尾数为零的数字也可排除 :如 10100。若一个数的末尾是 0,且它不是 0 本身,它就不可能是回文。

  3. 反转数字的一半

    • 每次将 x 的最后一位拼接到 reversedHalf 后面,同时将 x 缩短一位,直到 x 的长度小于或等于 reversedHalf
    • 如果数字的长度是偶数,则反转后的 reversedHalfx 应相等。
    • 如果数字的长度是奇数,则可以忽略 reversedHalf 的中间位(即 reversedHalf / 10),此时两者也应相等。

代码实现

cpp 复制代码
class Solution {
public:
    bool isPalindrome(int x) {
        // 负数或非零尾数为0的数无法成为回文数
        if (x < 0 || (x % 10 == 0 && x != 0)) return false;

        int reversedHalf = 0;
        while (x > reversedHalf) {
            reversedHalf = reversedHalf * 10 + x % 10;
            x /= 10;
        }

        // 判断两种情况:
        // 1. x == reversedHalf 表示偶数长度,反转完全相同
        // 2. x == reversedHalf / 10 表示奇数长度,忽略中间一位
        return x == reversedHalf || x == reversedHalf / 10;
    }
};

代码详解

  • x < 0 || (x % 10 == 0 && x != 0):这是排除负数和非零尾数为零的情况,这些数不可能是回文。

  • while (x > reversedHalf):每次将 x 的最后一位加到 reversedHalf 后面,缩短 x。这个过程在 x 的长度超过 reversedHalf 的长度时停止。

  • return x == reversedHalf || x == reversedHalf / 10:在循环结束后,有两种可能:

    • 若数字长度为偶数,则 x == reversedHalf
    • 若数字长度为奇数,则 x == reversedHalf / 10(忽略中间一位,见下面的例子)。

举例分析

x = 12321 为例,展示代码的运行过程:

  • 初始化x = 12321reversedHalf = 0
  • 第一轮循环
    • reversedHalf = reversedHalf * 10 + x % 10 = 0 * 10 + 1 = 1
    • x = x / 10 = 1232
  • 第二轮循环
    • reversedHalf = 1 * 10 + 2 = 12
    • x = 123
  • 第三轮循环
    • reversedHalf = 12 * 10 + 3 = 123
    • x = 12

循环结束后,reversedHalf123x12,可以看到 reversedHalf / 10 = 12,即 x == reversedHalf / 10 成立,因此 12321 是回文数。


复杂度分析

  • 时间复杂度:O(log₁₀(n)),因为我们只遍历数字的一半。
  • 空间复杂度:O(1),不需要额外空间。

总结

这个方法不仅优化了空间使用,还保证了执行效率,是一种优雅的实现方案。通过这种方式,我们可以轻松判断整数是否为回文。该解法具有优秀的时间和空间复杂度,是回文数问题的最佳解法之一。

相关推荐
程序猿阿伟3 分钟前
《C++中的魔法:实现类似 Python 的装饰器模式》
java·c++·装饰器模式
zyhomepage5 分钟前
科技的成就(六十四)
开发语言·人工智能·科技·算法·内容运营
Ethan Wilson11 分钟前
C++/QT可用的websocket库
开发语言·c++·websocket
想做白天梦23 分钟前
多级反馈队列
java·windows·算法
潇雷25 分钟前
算法Day12|226-翻转二叉树;101-对称二叉树;104-二叉树最大深度;111-二叉树最小深度
java·算法·leetcode
爱编程— 的小李42 分钟前
开关灯问题(c语言)
c语言·算法·1024程序员节
韭菜盖饭1 小时前
LeetCode每日一题3211---生成不含相邻零的二进制字符串
数据结构·算法·leetcode
manba_1 小时前
leetcode-146. LRU 缓存
leetcode
ergevv1 小时前
类的变量的初始化:成员初始化列表、就地初始化
c++·初始化·
极客代码1 小时前
C/C++ 随机数生成方法
c语言·开发语言·c++·算法