两数相加 II - 链表相加

445 阅读1分钟

正题

两数相加 II

给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。

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

示例1:

image.png

输入: l1 = [7,2,4,3], l2 = [5,6,4]
输出: [7,8,0,7]

示例2:

输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [8,0,7]

示例3:

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

解析:

看到图第一反应:这不是我们平时算加法的竖式吗?!那么归根到底,我们可以认为他是两个整数相加。所以我会想到第一个解决方案:转整相加

转整相加真的可行吗

拿图示为例:链表 7 -> 2 -> 4 -> 3 转成整数为 7243, 链表 5 -> 6 -> 4 转成整数为 564,然后做一个简单的加法 7243 + 564 = 7807,再将数按照位数从高到低转化为链表不就ok了嘛。

原理:

  1. 分别遍历链表
  2. l1l2分别转成 s1 s2
  3. s1 s2 转为 整数后相加得 res
  4. 创建新的链表,将 res每一位遍历压入链表中
var addTwoNumbers = function(l1, l2) {
    let p1 = l1
    let p2 = l2
    let s1 = ''
    let s2 = ''
    while(p1 || p2) {
        if (p1) {
            s1 += p1.val
            p1 = p1.next
        }
        if (p2) {
            s2 += p2.val
            p2 = p2.next
        }
    }
    let res = parseInt(s1) + parseInt(s2) + ''
    let head = new ListNode(res[0])
    let p = head
    for (let index = 1 ; index < res.length; index++) {
        p.next = new ListNode(res[index])
        p = p.next
    }
    return head
};

似乎没有任何问题,提交。

image.png

当测试用例到达 1561 个时,出现了 NaN,这是怎么回事?

开始找原因,尝试打印 res 后发现:

8.074864864864864e+60

原来链表的长度太长,转成整数后溢出了。。。

这样一来是不能通过的,并且有很大的限制,所以此方案不可行!

转换思路,反转链表

按照图示,我们需要先将两个链表的最后一位相加,再将倒数第二位和倒数第二位相加,但是链表是顺序的,无法回退,那么每一次相加都需要重新遍历。所以将链表反转无疑是解决这个问题优解!

反转后则变为 分别第一位和第一位相加,第二位和第二位相加,那么则只需要再遍历一次即可!

关于进位

当相加值大于等于10的时候,我们就会提到进位,那么下一位相加之后得到进位就 再+1,所以我们还需要一个标识,表示上一位相加是否有进位,那么当前的结果就为 (n1 + n2) % 10即可。

完成代码

  1. 首先需要实现链表的反转,具体可参考前面的文章: 一张图说明链表的反转

  2. 记录进位 isAdd

  3. 创建新的链表将结果压入新的链表,注意是否进位,若进位则结果上再 +1

  4. 链表遍历完后,最后再次判断进位

  5. 将结果再次反转即可

var transList = function (head) {
    let cur = head
  let pre = null
  while (cur) {
    const next = cur.next
    cur.next = pre
    pre = cur
    cur = next
  }
  return pre
}

var addTwoNumbers = function(l1, l2) {
    let tL1 = transList(l1)
    let tL2 = transList(l2)
    const res = new ListNode(0)
    let p = res
    let isAdd = false
    while(tL1 || tL2) {
        const number1 = tL1 ? tL1.val : 0
        const number2 = tL2 ? tL2.val : 0
        let res = isAdd ? number1 + number2 + 1 : number1 + number2
        isAdd = res >= 10
        p.next = new ListNode(res % 10)
        p = p.next
        tL1 = tL1 ? tL1.next : null
        tL2 = tL2 ? tL2.next: null
    }
    if (isAdd) {
        p.next = new ListNode(1)
    }

    return transList(res.next)
}