LeetCode 经典题:“回文数”

一、题目描述

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例

  • 示例 1
    • 输入x = 121
    • 输出true
  • 示例 2
    • 输入x = -121
    • 输出false
    • 解释:从左向右读为 -121 ,从右向左读为 121- ,因此它不是一个回文数。
  • 示例 3
    • 输入x = 10
    • 输出false
    • 解释:从右向左读为 01 ,因此它不是一个回文数。
  • 示例 4
    • 输入x = -101
    • 输出false

二、解题思路与多方法实现

方法一:转换为字符串法

思路

将整数转换为字符串,然后比较字符串与其反转后的字符串是否相同。如果相同,则该整数是回文数;否则,不是回文数。

代码实现(Java)
public class PalindromeNumber {
    public boolean isPalindrome(int x) {
        // 将整数转换为字符串
        String numStr = String.valueOf(x);
        // 反转字符串
        String reversedStr = new StringBuilder(numStr).reverse().toString();
        // 比较原字符串和反转后的字符串
        return numStr.equals(reversedStr);
    }
}
代码解释
  1. 整数转字符串:使用 String.valueOf(x) 将整数 x 转换为字符串 numStr
  2. 字符串反转:利用 StringBuilderreverse() 方法将 numStr 反转,得到 reversedStr
  3. 结果比较:使用 equals() 方法比较 numStrreversedStr,如果相等则返回 true,否则返回 false

方法二:数学方法(反转一半数字)

思路

通过数学运算反转整数的一半,然后将反转后的一半与原整数的前半部分进行比较。具体步骤如下:

  1. 负数不可能是回文数,直接返回 false
  2. 个位数为 0 且不为 0 的数也不是回文数,直接返回 false
  3. 不断地将整数的最后一位取出并添加到反转后的数中,同时将原数除以 10,直到反转后的数大于等于原数。
  4. 最后比较反转后的数与原数(当原数位数为偶数时)或者反转后的数除以 10 与原数(当原数位数为奇数时)是否相等。
代码实现(Java)
public class PalindromeNumberMath {
    public boolean isPalindrome(int x) {
        // 负数和个位数为 0 且不为 0 的数不是回文数
        if (x < 0 || (x % 10 == 0 && x != 0)) {
            return false;
        }

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

        // 当原数位数为偶数时,直接比较;当原数位数为奇数时,反转后的数除以 10 再比较
        return x == reversedNum || x == reversedNum / 10;
    }
}
代码解释
  1. 特殊情况判断:首先判断 x 是否为负数或者个位数为 0 且不为 0 的数,如果是则直接返回 false
  2. 反转一半数字:使用 while 循环,在 x > reversedNum 的条件下,不断将 x 的最后一位取出并添加到 reversedNum 中,同时将 x 除以 10。
  3. 结果比较:当 x 不大于 reversedNum 时,循环结束。此时如果原数位数为偶数,比较 xreversedNum 是否相等;如果原数位数为奇数,比较 xreversedNum / 10 是否相等。

方法三:逐位比较法

思路

通过不断获取整数的最高位和最低位进行比较,如果不相等则不是回文数。同时,去掉最高位和最低位,继续比较中间的数。

代码实现(Java)
public class PalindromeNumberDigitCompare {
    public boolean isPalindrome(int x) {
        if (x < 0) {
            return false;
        }

        int div = 1;
        // 找到能获取最高位的除数
        while (x / div >= 10) {
            div *= 10;
        }

        while (x > 0) {
            int left = x / div;
            int right = x % 10;
            if (left != right) {
                return false;
            }
            // 去掉最高位和最低位
            x = (x % div) / 10;
            div /= 100;
        }
        return true;
    }
}
代码解释
  1. 负数判断:负数不是回文数,直接返回 false
  2. 找到最高位除数:使用 while 循环找到能获取 x 最高位的除数 div
  3. 逐位比较:在 x > 0 的条件下,通过 x / div 获取最高位 left,通过 x % 10 获取最低位 right,比较它们是否相等。如果不相等则返回 false
  4. 去掉最高位和最低位:通过 (x % div) / 10 去掉最高位和最低位,同时将 div 除以 100。
  5. 结果返回:如果循环结束都没有返回 false,则说明是回文数,返回 true

三、复杂度分析

时间复杂度

  • 转换为字符串法:主要时间开销在于字符串反转,时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是整数的位数。
  • 数学方法(反转一半数字):只需要反转一半的数字,时间复杂度为 O ( l o g 10 n ) O(log_{10}n) O(log10n),其中 n n n 是整数的值。
  • 逐位比较法:需要逐位比较,时间复杂度为 O ( l o g 10 n ) O(log_{10}n) O(log10n),其中 n n n 是整数的值。

空间复杂度

  • 转换为字符串法:需要额外的字符串空间,空间复杂度为 O ( n ) O(n) O(n),其中 n n n 是整数的位数。
  • 数学方法(反转一半数字):只使用了常数级的额外空间,空间复杂度为 O ( 1 ) O(1) O(1)
  • 逐位比较法:只使用了常数级的额外空间,空间复杂度为 O ( 1 ) O(1) O(1)

四、总结

“回文数”这道简单题通过多种方法为我们展示了不同的解题思路。转换为字符串法简单直观,但需要额外的字符串空间;数学方法(反转一半数字)和逐位比较法在空间复杂度上更优,通过数学运算避免了字符串操作。在实际应用中,如果对空间要求不高,转换为字符串法是一种快速实现的方法;如果追求空间效率,数学方法则更为合适。希望通过对这道题的多种解法的学习,大家能在面对类似问题时,灵活选择最优的解决方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值