zoukankan      html  css  js  c++  java
  • JS leetcode 加一 题解分析

    壹 ❀ 引

    今天是刷leetcode的第三天,根据推荐优先刷数据结构相关的卡片,先把数据结构知识体系建立起来,不然就是题目无从下手答案也看不懂的尴尬局面。那么今天的题目是加一,老规矩,先记录自己的解题思路,再分析优质答案。

    题目如下:

    给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

    最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

    你可以假设除了整数 0 之外,这个整数不会以零开头。

    示例 1:

    输入: [1,2,3]
    输出: [1,2,4]
    解释: 输入数组表示数字 123。
    

    示例 2:

    输入: [4,3,2,1]
    输出: [4,3,2,2]
    解释: 输入数组表示数字 4321。
    

    那么本文开始。

    贰 ❀ 聪明但失策的方法

    我们先来分析题目,题目想表达的意思是给一个整数组成的非空数组,比如数字123装在数组中就是[1,2,3],我们得在123的基础上加1,所以输出得是[1,2,4]。注意,每个元素只能是单个数字,所以不会存在[1,20,4]类似的情况。

    我首先想到的就是对数组进行倒序遍历,比如看最后一位数字是否小于9,如果小于则直接把尾数加1,直接返回返回数组即可:

    if (arr[length - 1] < 9) {
        arr[length] += 1;
        return arr;
    };
    

    那么如果尾数是9,就得把尾数变成0,并将尾数前一位数字加1,可这样就麻烦了,如果前面尾数刚好又是9怎么办,那岂不是变成了10,题目要求每个数字只能有一位,所以像[9,9]加1就得变成[1,0,0]。

    当我还在想还要怎么处理时,突然灵机一动,不对啊,数字计算进位的事情交给数字自己去做不就好了,我为什么要花心思管,直接将数组转成数字,让数字自增1,再还原成数组岂不妙哉!

    于是我写了如下代码:

    var plusOne = function (digits) {
        // 1.将数组切割成字符串
        // 转数字并加1
        // 转字符串并再次切割成数组
        return (Number(digits.join("")) + 1).toString().split("");
    };
    

    拿官方给的两个例子测试了下,没问题,果断提交,然后挂了....

    具体挂在了[6, 1, 4, 5, 3, 9, 0, 1, 9, 5, 1, 8, 6, 7, 0, 5, 5, 4, 3]这个例子,正确答案很明显是[6, 1, 4, 5, 3, 9, 0, 1, 9, 5, 1, 8, 6, 7, 0, 5, 5, 4, 4],但我的代码却输出了["6", "1", "4", "5", "3", "9", "0", "1", "9", "5", "1", "8", "6", "7", "0", "5", "0", "0", "0"],这我就蒙圈了。

    经过一番百度,这才发现了Number能表示的正负安全范围为-253到253,而上述使用Number加1的数字为6145390195186705544,已经超过了有效范围。

    当然也不是没有解决方案,通过ES10的BigInt来解决数字超出范围失去精度问题,使用也比较简单,在数组默认加个n,经过修改:

    var plusOne = function (digits) {
        // 借用BigInt解决数字超出范围的问题
        return (BigInt(digits.join('')) + 1n).toString().split('');
    };
    

    OK,这下通过了测试。

    叁 ❀ 无法逃避的更佳实现

    上文的思路虽然很棒,跳出了看到数组本能想到遍历的固有思路,但致命缺陷是BigInt毕竟是ES10的东西,ES6都没完全得到浏览器支持,更何况说10,玩意面试遇到了这题被面试官也这么说,那不GG。

    所以我还是没能逃过最初的思路,让数组倒序遍历,并手动控制数字自增,比如[1,2]变成[1,3],像[9,9]我们可以先变成[0,0]再塞个1进去,上代码:

    /**
     * @param {number[]} digits
     * @return {number[]}
     */
    var plusOne = function (digits) {
        var last = digits.length - 1;
        while (last >= 0) {
            // 如果最后一位数小于9,那么自增加1就可以返回
            if (digits[last] < 9) {
                digits[last] += 1;
                return digits;
            } else {
                //反之加1等于10,所以先把这一位设置成0
                digits[last] = 0;
            };
            last--;
        };
        // 考虑到[9,9]的情况,遍历完就成了[0,0]了,所以得从头部加个1进去
        if (digits[0] == 0) {
            digits.unshift(1);
        };
        return digits;
    };
    

    注释已经写得很清楚了,这里就不多解释,而且这段代码虽然看起来比较多,但是运行时间要远远低于第一种实现方法。

    那么关于这道题就说到这里了,本文结束。

  • 相关阅读:
    Ubuntu下ClickHouse安装
    redis.conf配置详解(转)
    php使用sftp上传文件
    ubuntu下安装nginx1.11.10
    cookie和session的区别
    linux下Redis主从复制
    linux-ubuntu 安装配置Redis
    php的常量
    Ubuntu防火墙配置
    技术资料
  • 原文地址:https://www.cnblogs.com/echolun/p/12892038.html
Copyright © 2011-2022 走看看