題目描述:給定兩個非空鏈結串列,分別代表兩個非負整數。數字以逆序方式儲存,每個節點包含一位數字。請將兩個數字相加,並以鏈結串列的形式返回結果。例如,鏈結串列 2 → 4 → 3 代表整數 342,鏈結串列 5 → 6 → 4 代表整數 465,兩者相加結果為 807,即輸出 7 → 0 → 8。
解題思路:由於數字是逆序儲存的,鏈結串列的頭節點對應個位數,因此我們可以直接從頭開始逐位相加,模擬手算加法的過程。
核心步驟如下:
同步遍歷兩個鏈結串列:同時走訪 l1 和 l2,每次取出對應位置的值(若某個串列已到達尾端,該位值視為 0)。
計算當前位的和與進位:將兩個節點的值與前一輪的進位 carry 相加,得到 sum。當前位的值為 sum % 10,新的進位為 sum / 10。
建立新節點:為每一位建立新的 ListNode,將其串接到結果串列中。
處理最終進位:若兩個串列都遍歷完畢後,進位 carry 仍為 1,則需在末尾補上一個值為 1 的節點(例如 999 + 1 = 1000)。
使用一個虛擬頭節點(dummy head)可以簡化邊界處理,避免對結果串列的第一個節點進行特殊處理。整個過程的終止條件是 l1、l2 均為 nullptr 且 carry == 0。
時間複雜度:O(max(m, n)) — 其中 m 和 n 分別是兩個鏈結串列的長度。我們需要遍歷較長的那個串列,每個節點僅訪問一次。若有最終進位,則多執行一次迭代,但仍屬常數級的額外操作,不影響整體時間複雜度。
空間複雜度:O(max(m, n)) — 結果鏈結串列的長度最多為 max(m, n) + 1(+1 是因為可能存在最終進位),因此需要配置對應數量的新節點。除結果串列外,僅使用了固定數量的輔助變數(carry、sum、curr 等),不需要額外的資料結構。
1. Create a dummy head node and a current pointer pointing to it; set carry = 0. 2. Loop while l1 is not null OR l2 is not null OR carry != 0: a. Set sum = carry. b. If l1 is not null: sum += l1.val, advance l1 to l1.next. c. If l2 is not null: sum += l2.val, advance l2 to l2.next. d. Update carry = sum / 10. e. Create a new node with value sum % 10 and append it to current. f. Advance current to the new node. 3. Return dummy.next (the actual head of the result list).
遞迴解法 O(max(m,n)):將每一步的加法邏輯封裝成遞迴函式,傳入當前兩個節點及進位值,遞迴地建立結果節點。此方法邏輯清晰,但每次遞迴都會消耗呼叫堆疊空間,當串列極長時(數萬個節點)有堆疊溢位的風險,實際上不優於迭代解法。
轉換為整數再相加 O(max(m,n)):先將兩個鏈結串列各自還原為對應的整數,直接做整數加法後,再將結果轉換回鏈結串列。此方法直觀易懂,但當數字位數極大(超過 64 位元整數上限)時會發生溢位,因此在通用情境下並不可靠,面試中通常不被採納。