zoukankan      html  css  js  c++  java
  • JS leetcode 回文数 题解分析,数学不好是硬伤

    壹 ❀ 引

    每日一题环节,今天的一道是让我相信自己数学薄弱的题目,题目来源leetcode9. 回文数,题目描述如下:

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

    示例 1:

    输入: 121
    输出: true
    

    示例 2:

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

    示例 3:

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

    进阶:

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

    我们简单分析题目,来看看这道题该怎么做。

    贰 ❀ 题解分析

    题目进阶是不转字符串来做,我们也别进阶,看看站在字符串的角度能怎么做。

    题目关于回文数的描述也很清楚,不管从左还是从右,读起来都相同的数组,那这样无论位数为基数还是偶数,比如22212都死回文数,所以到这里,我第一想到的就是转字符使用双指针来做,先上代码:

    /**
     * @param {number} x
     * @return {boolean}
     */
    var isPalindrome = function (x) {
        // 转字符
        let x_ = x.toString(),
            ans = false;
        // 如果字符串长度为1直接返回
        if (x_.length === 1) {
            return true;
        };
        // 使用双指针
        let i = 0,
            j = x_.length - 1;
        while (i < j) {
            // 两两相对,左右同时取数字对比,只要一个不符合直接返回false
            if (x_.charAt(i) === x_.charAt(j)) {
                ++i;
                --j;
            } else {
                return ans;
            };
        };
        return true;
    };
    

    那么到这里可以补充两个小知识点,其实大家应该都知道,数字和字符串直接如何快速转换?,单说纯数字类型的字符,转数字可以用 + ,像这样:

    +"1"; //1
    +"120"; //120
    

    当然用API我们还可以用Number()parseInt(),浮点数还可以使用parseFloat()

    数字怎么快速转字符呢?我们可以直接用数字加上一个空字符,像这样:

    1+""; //"1"
    120+""; //"120"
    

    哎,有同学马上想到可以使用toString,没错,不过大家有没有发现一个这样的问题,小数点用toString没问题,整数就报错了,比如:

    1.3.toString(); //"1.3"
    1.toString(); // 报错 Uncaught SyntaxError: Invalid or unexpected token
    

    你想转整数,你还得这样写:

    1..toString(); //"1"
    

    这是因为,当我们写1.toString()时,JavaScript引擎把第一个点理解成了浮点数,所以在JavaScript看来,它就等同于(1.)toString(),所以我们得加两个点,可是这样写怪怪的,所以折中的做法是使用括号包裹整数,这样:

    (1).toString(); //"1"
    

    很显然,转成字符的思路非常不错,问题来了,既然转成了字符,那为啥不直接再转成数组,做一次翻转了还原直接对比呢,比如这样:

    /**
     * @param {number} x
     * @return {boolean}
     */
    var isPalindrome = function (x) {
        return x.toString() === x.toString().split("").reverse().join("");
    };
    

    简单明了,比双指针清晰多了。

    那么说完转字符串的做法之后,我们会想进阶的问题,能不能就站在数字的角度来解决这个问题呢,老实说,我这种大学没数学的人,敏感度确实差了,这里我先引用leetcode用户吕善柯-三七互娱站在数据角度,使用双指针的解决思路,因为这个是我最能理解一点的...其它数学解答我真的是懵的....我要写个惨字,代码如下:

    /**
     * @param {number} x
     * @return {boolean}
     */
    var isPalindrome = function(x) {
        if(x < 0) return false;
        if(x < 10) return true; 
        let right = 1;
        let left = 0;//初始为 x的总位数
        let sum = x;
        while(sum >= 1){//算出总位数
            sum /= 10;
            left++;
        }
        //获取第n位的数
        let getNum = (_x, n) => {
            return Math.floor(_x % Math.pow(10, n) / Math.pow(10, n - 1));
        }
        while(left > right){
            //分别取左右对称两位数字进行对比
            if(getNum(x, left) != getNum(x, right)){
                return false;
            };
            left--;
            right++;
        }
        return true;
    };
    

    我之所以希望转字符串,其实本质是想知道需要遍历几次,字符串有length,其次是能便捷获取对应下标的字符。

    而上述代码实现中,关于获取length使用的是如下代码:

    let left = 0;
    while (sum >= 1) { //算出总位数
      sum /= 10;
      left++;
    }
    

    比如数字3223,让这个数不断的除以10,因为一旦比1小,那说明此时数字0.3223了,一共除了4次,说明这是四位数。

    知道这个之后我们要做的就是取对应位的数字,比如第一次要取第一位3和最后一位3,可以直接站在答案的角度来说,第一个3就是用3223/1000得到3.223,然后通过floor像下取整拿到3。而最后一位3则是让3223%10,最后得到的3。

    所以我觉得我这个脑袋,真的是想不上去的,解题中使用了一个right和left,right表示个位数,是从1开始,而left是总位数,每次比较一个递减一个递增,就这么靠着Math.pow()这个api以及left与right的变化,就把每次对比的数取出来了,思路我是懂了,就是真的让自己做想不上去,背下来吧估计以后也会忘,我感觉有空我还得学学数学,扎心了。

    那么关于本题就分析到这里了。

    另外,我有232个粉丝了,粉丝数也是回文数!!!!

  • 相关阅读:
    Redis21:客户端与服务器端的通信与redis管道
    Redis20:keys、scan、bigkeys、查看key的存储方式
    Redis19:限流
    Redis18:分布式锁
    Redis17:cluster集群
    Redis16:两种redis集群解决方案:codis和cluster
    Android : 获取声卡信息的测试代码
    Android : 基于alsa库的音乐播放
    Android system :灯光系统_HAL_lights
    Android system :led_class驱动
  • 原文地址:https://www.cnblogs.com/echolun/p/13095370.html
Copyright © 2011-2022 走看看