LeetCode-0002两数相加(JavaScript版本)

373 阅读3分钟

2. 两数相加

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

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

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

示例 1:

img

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

题目分析

两个数字以逆序方式存储在链表中,返回两个数相加的结果链表(也是逆序存储的)

解法分析

这里是逆序存储的,遍历链表就是从个位开始,符合加法的习惯顺序

题目主要考察链表双指针技巧和加法运算过程中对进位的处理

链表算法题常见【虚拟头结点】技巧,也就是dummy节点,可以避免处理初始的空指针情况,降低代码的复杂性

使用虚拟头节点

/**
 * Definition for singly-linked list.
 */
function ListNode(val, next) {
    this.val = (val === undefined ? 0 : val)
    this.next = (next === undefined ? null : next)
}

// 使用头节点
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
let addTwoNumbers = function(l1, l2) {
    let list1 = l1;
     let list2 = l2;
     // 虚拟头节点
     let templist = new ListNode(-1);
     // 第一次挂载
     let result = templist;
     let carry = 0; // 进位
     // 开始执行加法,两条链表走完且没有进位时才能结束循环
     while (list1 || list2 || carry) {
         let sum = carry;
 
         if (list1) {
             sum += list1.val;
             list1 = list1.next;
         }
 
         if (list2) {
             sum += list2.val;
             list2 = list2.next;
         }
 
         carry = Math.floor(sum / 10); // 进位值
         sum = sum % 10;

         // 构建新节点
         templist.next = new ListNode(sum % 10);
           // console.log('templist',templist);
          //  console.log('result',result);
         // templist指向改变,result指向不变,所以最后返回的是result.next 去掉虚拟头节点的值
         templist = templist.next;
 
     }
     // 返回结果链表的头结点(去除虚拟头结点) result是templist
     return result.next;
 
 };
let l1_1 = new ListNode(2);
let l1_2 = new ListNode(4);
let l1_3 = new ListNode(3);
l1_1.next = l1_2;
l1_2.next = l1_3;
let l2_1 = new ListNode(5);
let l2_2 = new ListNode(6);
let l2_3 = new ListNode(4);
l2_1.next = l2_2;
l2_2.next = l2_3;
const input1 = l1_1;
const input2 = l2_1;
let result = addTwoNumbers(input1, input2);
console.log(result);

不使用虚拟头节点

/**
 * Definition for singly-linked list.
 */
function ListNode(val, next) {
    this.val = (val === undefined ? 0 : val)
    this.next = (next === undefined ? null : next)
}

// 不使用头节点
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
let addTwoNumbers = function(l1, l2) {
    let list1 = l1;
    let list2 = l2;
    let templist ;
    let result ;
    let carry = 0; // 进位

    // 开始执行加法,两条链表走完且没有进位时才能结束循环
    while (list1 || list2 || carry) {
        let sum = carry;

        if (list1) {
            sum += list1.val;
            list1 = list1.next;
        }

        if (list2) {
            sum += list2.val;
            list2 = list2.next;
        }

        carry = Math.floor(sum / 10); // 进位值

        sum = sum % 10;

        if (!templist) {
            // 第一次创建节点
            result = new ListNode(sum);
            templist = result;
        } else {
            // 创建新节点
            templist.next = new ListNode(sum);
            // templist指向改变,result指向不变,所以最后返回的是result
            templist = templist.next;
        }

    }
    return result;

};
let l1_1 = new ListNode(2);
let l1_2 = new ListNode(4);
let l1_3 = new ListNode(3);
l1_1.next = l1_2;
l1_2.next = l1_3;
let l2_1 = new ListNode(5);
let l2_2 = new ListNode(6);
let l2_3 = new ListNode(4);
l2_1.next = l2_2;
l2_2.next = l2_3;
const input1 = l1_1;
const input2 = l2_1;
let result = addTwoNumbers(input1, input2);
console.log(result);

总结小技巧

链表中使用虚拟头节点技巧,定义一个临时变量,存储下一个节点,最后结果在原来的位置不动

如果是使用了虚拟头节点,最后节返回的是result.next,如果不使用虚拟头节点,最后返回的是result