【算法实战之力扣刷题】两数相加

110 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

题目描述:

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

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

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

示例:

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

解题思路:

循环遍历两个链表,计算每个节点相加的和,再加当前节点位置的进位值,然后计算进位。

  1. 循环依次取出两个链表的最低位(因为每位数字都是按照逆序的方式存储的,这个第一次的最低位就是输入数组的第一位);

  2. 依次求出最低位的和,和进位值相加,作为当前计算的值,

  3. 更新链表当前节点的位置(连接链表头和当前节点的值)

  4. 返回链表的值

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


var addTwoNumbers = function(l1, l2) {
    // head 链表头  tail 链表当前节点位置
    let head = null, tail = null;
    //进位值
    let carry = 0;
    while (l1 || l2) {//循环l1,l2链表
        // 链表中当前节点位置的值
        const n1 = l1 ? l1.val : 0;
        const n2 = l2 ? l2.val : 0;
        const sum = n1 + n2 + carry;//当前计算的值:两链表节点相加,再加进位
        if (!head) {
            head = tail = new ListNode(sum % 10);//当没有节点的时候新建节点。%10是因为我们的计算结果是有可能大于10,所以需要取余
        } else {
            tail.next = new ListNode(sum % 10);//链表向下链接:有节点的时候则加入tail节点的后面
            
            tail = tail.next;// 更新链表节点位置
        }
        carry = Math.floor(sum / 10);//求进位(满十进一)
        if (l1) {//移动l1指针,指向下一个节点
            l1 = l1.next;
        }
        if (l2) {//移动l2指针
            l2 = l2.next;
        }
    }
    //最后一位节点是否有进位
    if (carry > 0) {
        tail.next = new ListNode(carry);
    }
    return head;
};

image.png

知识点:链表

链表是由一些元素(节点)组成的集合,并且存储数据元素的内存空间可以连续,也可以不连续。每个节点(node)都由数据本身和一个指向后续节点的指针组成。

一个单链表 (SinglyLinkedList) 的节点(node)由以下几部分组成:

  • 数据域(data):保存数据
  • 指针域(next):保存“下一个节点地址”的指针

image.png

链表与数组的区别:

链表和数组都是线性数据结构。

数组:存储需要一块连续的内存空间,数组做增删或者插入操作,可能需要移动大量的元素。

链表:存储不需要一块连续的内存空间,通过“指针”将节点连接起来。增删元素,不需要移动元素,只需要改next的指向即可。