Medium草稿★★★★O(max(n, m)) 時間 · O(1) 空間
Linked ListMath
Patterns⛓️ 鏈結串列操作🧮 數學・組合
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

2Add Two NumbersLinked ListMediumLinked List

給定兩個非空鏈結串列,代表兩個非負整數。數字以反向儲存,每個節點包含一個位數。將兩數相加並以鏈結串列形式回傳結果。

Example:

Input: l1 = [2,4,3], l2 = [5,6,4] Output: [7,0,8] Explanation: 342 + 465 = 807

Intuition

TIP

核心思路:模擬直式加法,從最低位開始逐位相加,注意進位處理。

Approaches

1. Recursive — O(max(n, m)) / O(max(n, m))
  • Idea: 遞迴處理每一位的加法,將進位傳遞給下一層
  • Time: O(max(n, m)) - n、m 為兩串列長度
  • Space: O(max(n, m)) - 遞迴呼叫堆疊
class Solution {
    fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? {
        return add(l1, l2, 0)
    }

    private fun add(l1: ListNode?, l2: ListNode?, carry: Int): ListNode? {
        if (l1 == null && l2 == null && carry == 0) return null

        val sum = (l1?.`val` ?: 0) + (l2?.`val` ?: 0) + carry
        val node = ListNode(sum % 10)
        node.next = add(l1?.next, l2?.next, sum / 10)

        return node
    }
}
⭐ 2. Iterative with Dummy Head — O(max(n, m)) / O(1)
  • Idea: 使用 dummy head,逐位相加兩串列節點的值加上進位,建立新節點接到結果串列
  • Time: O(max(n, m)) - 遍歷較長的串列
  • Space: O(1) - 除了輸出外只用常數空間
class Solution {
    fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? {
        val dummy = ListNode(0)
        var curr = dummy
        var p1 = l1
        var p2 = l2
        var carry = 0

        while (p1 != null || p2 != null || carry != 0) {
            val sum = (p1?.`val` ?: 0) + (p2?.`val` ?: 0) + carry
            carry = sum / 10
            curr.next = ListNode(sum % 10)
            curr = curr.next!!
            p1 = p1?.next
            p2 = p2?.next
        }

        return dummy.next
    }
}

WARNING

最後的 carry != 0 條件容易遺漏。例如 [9,9] + [1] = [0,0,1],若忘記處理最後的進位,結果會少一位。

🔑 Takeaways