嘿嘿~今天我們要來挑戰一道非常有趣的題目——Add Two Numbers(加法運算的鏈結串列表示)!
這題要求我們將兩個用反序鏈結串列表示的非負整數加起來,並將結果以同樣的鏈結串列形式返回。
這聽起來是不是有點像在處理小學的算術題呢?但其實這道題目能夠考驗我們如何處理進位邏輯和操作鏈結串列。那我們就一起來看看解法吧!
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
題目描述:
給定兩個反序鏈結串列,分別代表兩個非負整數,要求將兩個數字相加,並返回其加總結果的鏈結串列形式。
你可以假設這兩個數字沒有任何前導零,除了數字 0
本身。
Example 1:
難度:Medium
範例 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]
我們可以遍歷兩個鏈結串列,從每個節點取出對應的數字進行加法運算,同時處理進位,並將結果存入新的鏈結串列中:
class ListNode {
val: number;
next: ListNode | null;
constructor(val?: number, next?: ListNode | null) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}
function addTwoNumbers(l1: ListNode | null, l2: ListNode | null): ListNode | null {
let dummy = new ListNode(0); // 用來連接結果鏈結串列的虛擬頭節點
let p = l1, q = l2, current = dummy;
let carry = 0; // 用來保存進位
while (p !== null || q !== null) {
const x = (p !== null) ? p.val : 0;
const y = (q !== null) ? q.val : 0;
const sum = carry + x + y;
carry = Math.floor(sum / 10); // 計算進位
current.next = new ListNode(sum % 10); // 將計算結果的個位數存入當前節點
current = current.next; // 移動到下一個節點
if (p !== null) p = p.next;
if (q !== null) q = q.next;
}
// 若最後仍有進位,則新增一個節點存儲進位值
if (carry > 0) {
current.next = new ListNode(carry);
}
return dummy.next; // 返回虛擬頭節點的下一個節點,為實際的加總結果
}
逐位相加並處理進位
我們將兩個鏈結串列的對應節點相加,並處理進位情況。
每次加法時,我們將兩個數字加上上一輪的進位,並將結果拆分為個位數和進位。例如,7 + 5 = 12
,個位數是 2
,進位是 1
。
處理鏈結串列不同長度的情況
我們在遍歷時,如果某個鏈結串列的長度比另一個短,則可以用 0
作為該位置的值,這樣就避免了長度不一致帶來的問題。
額外處理最後的進位
當我們遍歷完所有的節點後,可能還會有剩餘的進位。如果有,我們需要在結果鏈結串列的最後新增一個節點來存儲這個進位。
這種處理方式的核心在於保持計算的簡潔性和高效性,使用一個指針同時遍歷兩個鏈結串列,並即時處理進位情況。
這樣的做法不需要事先反轉鏈結串列或使用額外的空間來存儲中間結果,使得解法的時間複雜度為 O(n),且空間複雜度也保持在 O(n)。
0
填補。鏈結串列(Linked List)是一種線性數據結構,由一組節點(Node)組成,其中每個節點包含兩個部分:
單向鏈結串列(Singly Linked List):每個節點只指向下一個節點,沒有指向前一個節點。
[Data | Next]
雙向鏈結串列(Doubly Linked List):每個節點有兩個指標,分別指向前一個節點和下一個節點。
[Prev | Data | Next]
環狀鏈結串列(Circular Linked List):最後一個節點的指標指向第一個節點,形成環狀結構。
class ListNode {
val: number;
next: ListNode | null;
constructor(val?: number, next?: ListNode | null) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}
在這個範例中,每個 ListNode
都包含一個 val
(數據值)和一個 next
(指向下一個節點的指標)。
解完這道題目,是不是覺得加法運算變得沒那麼可怕了呢?
其實,就像寫程式一樣,人生中遇到的難題,也都是一步步累積出來的,每解決一個問題就離成功更近一點~
希望大家能帶著這份成就感,繼續面對每個挑戰!
加油喔!我們下次再一起突破更多有趣的題目~٩(^ᴗ^)۶💙