leetcode刷题记录-2. 两数相加 - 初识 js 链表

189 阅读1分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

前言

今天的每日一题为困难,看了一下各大题解,感觉难度过大,很难自己理解,直接cv大法,并且又去找了一题当作今天的练习。没想到找到的这道题也是满满的坑,之前从来没有听说过 js 的链表类型,今天第一次见到,刚开始以为当成数组处理岂不是非常简单,后来才发现没那么简单。

题目描述

今天的题目为leetcode上的 2.两数相加 难度为 中等

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

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

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

image.png

示例 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
  • 题目数据保证列表表示的数字不含前导零

题解

最开始的时候当成数组来做解答,结果根本过不去leetcode的编译器,一直报错,直到我去搜了一下 js 的链表类型,才发现虽然他长得和数组很像,但是数组上面的方法它基本没有,所以才会一直报错。

不信邪之路

刚开始我还不信邪,不就是链表嘛,那我把你转成数组,解决完问题之后在转换回来,一样能做的出来。结果在我做完这一系列复杂操作之后,一个错误信息让我放弃了:

image.png

原来我审题审的不够充分,题目中因为是逆序的,所以一旦一方的长度过长,那么作为数组相加的话结果完全不一样。看来链表的结构和数组差距真的有点大,所以果断放弃转换的这种方式,开始去了解一下链表的结构都有些什么。

链表结构

通过在leetcode中使用 console.log 大法和上网差一些关于 ListNode 的资料,初步了解了,它是一个对象,并且其中两个属性,一个 val 会返回当前链表指向的值,一个 next 会返回一个指向下一个节点的 ListNode

console.log("l1:",l1);
console.log("typeof l1:",typeof l1);
console.log("l1.val:",l1.val);
console.log("l1.next:",l1.next);
let node = l1.next
console.log("node.val:",node.val);

image.png 并且,新建一个链表在其中添加值的话,我们只能通过一个一个值添加,并且将某一项的next赋值为另一项的val这种方式,举一个简单的例子:

let node
let head =  new ListNode(sum[0])
let pnode = head

for(let i = 1; i < sum.length; i++) {
    node =  new ListNode(sum[i])
    pnode.next = node  
    pnode = node  
}

head就是我们的新链表,我们只能不断地给它的next赋值来扩充它。

这样我们就初步了解了 ListNode 的相关属性,理论存在,开始做题。

链表解题

由于两个链表都是逆序存储数据的,刚好满足链表的val和next方法的前进方向,所以两个链表同一个位置的数字可以直接同步相加,然后一起next。
我们遍历两个链表,并且计算每一位上面的和,当这个和大于等于10的时候,就要向前进一位。我们用node1和node2来表示当前位的链表的值,并且维护一个进位的值为carry初始为0,当node1和node2相加大于9的情况下,我们就把carry的值变为1,并且下一次相加的值就会变为node1+node2+carry,并且下一项就要去判断node1+node2+carry是否大于9,大于则carry不变,小于则carry归0。

如果有一个链表先next结束了,那么接下去的值都默认为0,并且如果两个链表都next结束了,carry的值还是为1,那么在最后的链表的尾部要添加一位。

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
    let head = null;
    let pnode = null;
    let carry = 0;
    while (l1 || l2) {
        const node1 = l1 ? l1.val : 0;
        const node2 = l2 ? l2.val : 0;
        const sum = node1 + node2 + carry;
        if (!head) {
            head = pnode = new ListNode(sum % 10);
        } else {
            pnode.next = new ListNode(sum % 10);
            pnode = pnode.next;
        }
        carry = Math.floor(sum / 10);
        if (l1) {
            l1 = l1.next;
        }
        if (l2) {
            l2 = l2.next;
        }
    }
    if (carry > 0) {
        pnode.next = new ListNode(carry);
    }
    return head;
};

image.png