[LeetCode] 兩數相加 (JavaScript 解法)


原題地址: https://leetcode-cn.com/problems/add-two-numbers/

 

題目描述

給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,並且它們的每個節點只能存儲 一位 數字。

如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。

您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。

 

題目示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807
 

[假] JavaScript 輸入

[2,4,3]
[5,6,4]

[假] JavaScript 輸出

[7, 0, 8]

 

真實的 JavaScript 輸入

這里有一個很坑的地方是雖然上面的輸入和輸出是數組,但是並不能按照數組輸入輸出,因為函數上明確寫了,輸入的是 ListNode 類型。

我在做這個的時候就被數組給迷惑了,怎么輸出都是 undefined。

 

而默認 ListNode 這個數據類型是已經存在的,因此在本地寫代碼的時候,是需要構造 l1 和 l2 兩個數據的,否則我不相信憑空就能寫出題解來。

首先我們已經知道,l1 和 l2 都是 ListNode 類型,因此輸入 [2, 4, 3] 中的 2 / 4 / 3 分別是每個 ListNode 的 val。

因此 l1 可以如下構造:

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;

// l1 = l1_1 

  

同樣的 l2 輸入可以如下構造:

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;

// l2 = l2_1;

  

因此本地寫代碼調用的時候實際上如下所示:

const input1 = l1_1;
const input2 = l2_1;

console.log(addTwoNumbers(input1, input2));

  

 

真實的 JavaScript 輸出

從注釋上可以發現,最終的輸出也是 ListNode 類型的,因此最終輸出結果應該如下:

ListNode {
  val: 7,
  next: ListNode { val: 0, next: ListNode { val: 8, next: null } } }

  

 

 

JavaScript 題解

當理解了 l1 和 l2 都是 ListNode 類型之后,就很好去做這個事情了。

下面代碼很簡單,主要是兩部分:

  • 鏈表的便利
  • 個位數相加 、 進位

具體的流程已經寫到了注釋上。

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {
    let resNode = new ListNode(0); // 臨時使用的 node 用來不停的增加鏈表節點
    let result = resNode; // 第一次掛載
    let tmpS = 0; // 相加 > 10 的進位數(1 或 0)
    while(l1 || l2 || tmpS) { // 判斷 tmpS 的目的是防止最后還有一位進位需要前置
        let val1 = l1 ? l1.val || 0 : 0; // 需要判斷 l1 是 null
        let val2 = l2 ? l2.val || 0 : 0; // 需要判斷 l2 是 null
        let sum = val1 + val2 + tmpS; // this.val 相加並加上進位值
        tmpS = sum >= 10 ? 1 : 0; // 計算本次相加是否需要進位
        sum = sum % 10; // 當前位只需要個位數
        if(l1) l1 = l1.next; // 遍歷鏈表
        if(l2) l2 = l2.next; // 遍歷鏈表
        resNode.next = new ListNode(sum); // 將當前結果掛到臨時的 node 上
        resNode = resNode.next; // 如果要繼續掛載鏈表,需要將當前的指針移動到 next 上
    }
    return result.next; // result 是 resNode, resNode.next 才是最終結果
};

  

需要注意的是,resNode 這個鏈表,需要每次將當前的指針移動到下一個 ListNode,可以打印 resNode 觀察過程:

// 打印位置:
// resNode.next = new ListNode(sum); // 將當前結果掛到臨時的 node 上
// console.log(resNode);
// resNode = resNode.next; // 如果要繼續掛載鏈表,需要將當前的指針移動到 next 上

ListNode { val: 0, next: ListNode { val: 7, next: null } }
ListNode { val: 7, next: ListNode { val: 0, next: null } }
ListNode { val: 0, next: ListNode { val: 8, next: null } }
// 打印位置:
// resNode.next = new ListNode(sum); // 將當前結果掛到臨時的 node 上
// resNode = resNode.next; // 如果要繼續掛載鏈表,需要將當前的指針移動到 next 上
// console.log(resNode);

ListNode { val: 7, next: null }
ListNode { val: 0, next: null }
ListNode { val: 8, next: null }

  

雖然每次 resNode 都被重新賦值,對於 result 來說,只是指針移動而已,因此它會擁有完整的鏈表。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM