图解leetcode - 两数相加(难度中)

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:
在这里插入图片描述

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

每个链表中的节点数在范围 [1, 100] 内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

不考虑精度

最开始不考虑精度写了一遍:

function ListNode(val, next) {
    this.val = (val === undefined ? 0 : val)
    this.next = (next === undefined ? null : next)
}

var addTwoNumbers = function(l1, l2) {
    let str1 = decompose(l1)
    let str2 = decompose(l2)
    let num3 = Number(reverse(str1)) + Number(reverse(str2))
    let l3 = generate(reverse(num3))
    return l3

    //@parame {String}
    //@return {ListNode}
    function generate(num, i = 0) { //字符串生成节点
        if (i == num.length) {
            return null
        }
        let no = Number(String(num)[i])
        return new ListNode(no, generate(num, i + 1))
    }
    //@parame {ListNode}
    //@return {String}
    function decompose(node) {  //节点分解为字符串
        if (!node.next) {
            return node.val
        }
        let str = ''
        str += node.val
        while (node.next) {
            node = node.next
            str += node.val
        }
        return str
    }

    //@parame {String|Number}  
    //@return String
    function reverse(num) {  //翻转
        return num.toString().split('').reverse().join('')
    }
};
console.log(addTwoNumbers(
    new ListNode(1, new ListNode(5)),
    new ListNode(5, new ListNode(6, new ListNode(4)))
))

因为:

  • JS 中整数的最大安全范围可以查到是:9007199254740991

显然不能用两个数字简单相加来得到答案,按照上述思路,可以简单地修改一下得到正确答案

轻松秒杀

经过优化后,改变了数据结构,认为数组更易于操作

var addTwoNumbers = function(l1, l2) {
    let array1 = decompose(l1)
    let array2 = decompose(l2)
    let array3 = add(array1, array2)
    return generate(array3)

    //@param {Number[],Number[]}
    //@return {Number[]}
    //@description 大数相加
    function add(arr1, arr2) {

        let len = Math.max(arr1.length, arr2.length)

        while (arr1.length < len) arr1.push(0)
        while (arr2.length < len) arr2.push(0)

        let arr = new Array(len)  //fill不能改变数组长度,所以先要声明
        arr.fill(0) 

        for (let i = 0; i < len; i++) {
            arr[i] += arr1[i] + arr2[i]
            arr[i + 1] = Math.floor(arr[i] / 10)
            arr[i] %= 10
        }
        if(arr[arr.length-1] == 0) { //去除由于没有产生进位而多余的0
            arr.pop()
        }

        return arr
    }

    //@param {String}
    //@return {ListNode}
    function generate(num, i = 0) {
        if (i == num.length) {
            return null
        }
        return new ListNode(num[i], generate(num, i + 1))
    }
    
    //@param {ListNode}
    //@return {Number[]}
    function decompose(node) {
        if (!node.next) {
            return [node.val]
        }
        let arr = []
        arr.push(node.val)
        while (node.next) {
            node = node.next
            arr.push(node.val)
        }

        return arr
    }
};
console.log(addTwoNumbers(  //测试例子
    new ListNode(5, new ListNode(1)),
    new ListNode(5, new ListNode(4, new ListNode(9)))
))
  • 采用了模块化的思想,因而占用较多内存,但流程清晰,易于理解:
    在这里插入图片描述

总结与反思

思路分三步走

  • 把链表节点变为数组
  • 生成相加后的数组
  • 把数组还原回链表

本题思想不难,但却特别容易出错,要求对以下几点掌握牢固

  • 大数加法的js实现,清楚特殊数据的输入与对应的输出
  • 熟悉用js表示的链表结构,会遍历和生成链表
  • 明确题目可能的数据输入,做对应算法的调整
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值