LeetCode刷题挑战:9. 回文数

710 阅读1分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

题目

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。

示例 1:

输入:x = 121
输出:true

示例 2:

输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。

示例 4:

输入:x = -101
输出:false  

提示:-231 <= x <= 231 - 1  

进阶:你能不将整数转为字符串来解决这个问题吗?

解题思路

通过之前的题目 7.整数反转 我们可以得知反转整数的方法有一下两种:

  • 将整数转换为字符串再转为数组进行反转
  • 通过数学方法取余求模可以得到

如果我们再比较反转后得到的数与之前的数是否相等,则可以判断是否为回文数。

如果相等,则返回true;否则返回false

同时根据示例我们可以得到一下特点:

  • 小于0的数不可能是回文
  • 大于0小于10的数一定是回文
  • 位数为偶数个的时候不可能是回文

方法一:整数反转 - 数组

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
    return parseInt(x.toString().split('').reverse().join('')) === x ? true : false;
};

方法二: 整数反转 - 取余

这种方法下需要考虑到x的正负。

同时因为会改变传进来的x的值,我们需要在一开始的时候保存一下。

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
    let temp = x;
    let reserve = 0;
    if (x < 0) return false;
    if (x < 10) return true;
    while(x !== 0) {
        reserve = reserve * 10 + x % 10;
        x = x/10 | 0;
    }
    reserve = (reserve | 0) === reserve ? reserve : 0;
    if (reserve === temp) return true;
    return false;
};

看到了大佬更好的解法如下:

var isPalindrome = function(x) {
    if(x < 0 || (!(x % 10) && x)) return false;
    let x2 = x, res = 0;
    while(x2){
        res = res * 10 + x2 % 10;
        x2 = ~~(x2 / 10);
    }
    return res === x;
};

方法三:转字符串后循环比较

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
    if (x >= 0) {
        str = x.toString();
        for (let i = 0; i < str.length / 2; i++) {
            if (str[i] !== str[str.length - 1 - i]) return false;
        }
        return true;
    } else {
        return false;
    }
};

方法四:转为字符串后双指针

  • 现将数字转为字符串
  • 自定义两个指针,一个指向最左边left,一个指向字符串最右边right
  • 循环条件是left < right的时候,判断指针指向的值是否相等,不等则返回false。
  • 否则左边指针向右移1
  • 右边指针左移1

此处判断的是不相等的时候返回false。

为什么不判断相等呢?

我们需要考虑到x = 0 的情况, 其实就不能进循环内部了,所以应该在外面返回true。

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function(x) {
    const str = new String(x);
    let left = 0, right = str.length - 1;
    while(left < right) {
        if(str[left] !== str[right]) return false;
        left++;
        right--;
    }
    return true;
};

方法五:数学法,除法和取余,数量级

此方法其实同方法二差不多,唯一的区别就是利用了数学里面的数量级来获取位数,而不是通过转为字符串获取。

使用除法和求余获得对应位置的数字,无字符串操作。

  • 首先获取当前数量级n

image.png

  • 通过x / n 获取首位。
  • 通过x % 10 获取末位。
  • (x % n) / 10 去除首位和末位,(x % n去除首位,x / 10去除末位),x 位数减 2。
  • n /= 100 x 位数减 2, 故n需要除 10^210

以 123421 为例,运算过程如下:

xnx/nx%10
-12342110000011
234210022
341034

代码:

/**
 * @param {number} x
 * @return {boolean}
 */
var isPalindrome = function (x) {
    if (x < 0) return false;
    if (x < 10) return true;
    let n = 10 ** Math.floor(Math.log10(x));
    while (n > 1 && x > 0) {
        if (Math.floor(x / n) !== x % 10) return false;
        x = Math.floor((x % n) / 10);
        n /= 100;
    }
    return true;
};