DSAPrep
MediumLinked List

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.

Example 1

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

Example 2

Input: l1 = [0], l2 = [0]
Output: [0]

Example 3

Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output: [8,9,9,9,0,0,0,1]

Constraints

  • The number of nodes in each linked list is in the range [1, 100].
  • 0 <= Node.val <= 9
  • It is guaranteed that the list represents a number that does not have leading zeros.
View original on LeetCode β†—

Because digits are stored least-significant-first, this is really elementary school addition read left to right: add the two current digits plus any carry, keep the ones digit, carry the tens digit forward. The reversed storage order is what makes that easy β€” no need to align digits from the right first.

Convert to Integers

Time O(n + m)Space O(n + m)

Walk each list once to reconstruct the actual integer it represents, add the two integers with normal Python arithmetic, then walk the digits of the sum to build a new list. This works because Python integers have unbounded precision, but it does not generalize to languages with fixed-width integers, and it still needs O(n + m) space for the result list regardless.

class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode | None, l2: ListNode | None) -> ListNode | None:
def to_int(node: ListNode | None) -> int:
num, place = 0, 1
while node:
num += node.val * place
place *= 10
node = node.next
return num
total = to_int(l1) + to_int(l2)
if total == 0:
return ListNode(0)
dummy = ListNode()
tail = dummy
while total:
tail.next = ListNode(total % 10)
tail = tail.next
total //= 10
return dummy.next

Simple, but it treats the lists as numbers to parse rather than working with the list structure directly β€” the pointer-based approach below is both more general and no more complex.

Digit-by-Digit With Carry

OptimalTime O(max(n, m))Space O(max(n, m))

Walk both lists simultaneously, adding corresponding digits plus a running carry. Treat a missing node (one list shorter than the other) as digit 0. Keep going as long as there are digits left in either list or a carry still needs to be placed β€” that last case is what produces the extra leading digit in 999... + 9999.

class Solution:
def addTwoNumbers(self, l1: ListNode | None, l2: ListNode | None) -> ListNode | None:
dummy = ListNode()
tail = dummy
carry = 0
while l1 or l2 or carry:
v1 = l1.val if l1 else 0
v2 = l2.val if l2 else 0
total = v1 + v2 + carry
carry = total // 10
tail.next = ListNode(total % 10)
tail = tail.next
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
return dummy.next

Tracing l1 = [2,4,3] (342), l2 = [5,6,4] (465) β€” building the result list one digit at a time:

7
β–²tail
1 / 3

2 + 5 + carry(0) = 7. No carry out. Append digit 7.

Why it’s correct: this mirrors manual addition digit by digit from the least-significant end, which is exactly the order these lists are already stored in β€” the carry correctly propagates overflow into the next position, and continuing the loop while carry is truthy handles the case where the sum has one more digit than either input (e.g. 9999999 + 9999). Complexity: each list is walked once, with the longer list determining the number of iterations, plus at most one extra digit for a final carry β†’ O(max(n, m)) time. The output list has at most max(n, m) + 1 nodes β†’ O(max(n, m)) space β€” optimal, since the result must contain at least as many digits as the larger input.