Problem
You have two linked lists where each node holds a single digit of a non-negative integer, stored least significant digit first. Add the two numbers together and return the result in the same reversed format.
Example โ [2,4,3] + [5,6,4]:
[2,4,3]
[5,6,4]
- Input: l1 = [2,4,3], l2 = [5,6,4]
- Output: [7,0,8]
- Explanation: 342 + 465 = 807, stored reversed as [7,0,8]
Counter-example โ lists of different length with a final carry:
[9,9]
[1]
- Input: l1 = [9,9], l2 = [1]
- Output: [0,0,1]
- Explanation: 99 + 1 = 100, stored reversed as [0,0,1]; forgetting the final carry here gives the wrong answer [0,0]
Intuition
Because the digits are stored in reverse order, the head of each list is already the ones place โ exactly where elementary-school addition starts. Walk both lists in lockstep, sum the two digits plus any carry from the previous column, and emit the result digit. The tricky part is knowing when to stop: you must continue until both lists are exhausted and there is no remaining carry.
Solution โ Iterative Digit Simulation
Traverse both lists simultaneously, computing the column sum at each position as digit_one + digit_two + carry. Append a new node with column_sum % 10 and propagate carry = column_sum // 10 to the next iteration. A dummy head node eliminates the special case of setting the result head.
- Create a
dummy_headnode and acurrentpointer starting there; setcarry = 0. - Loop while either list still has nodes or
carryis non-zero. - Treat an exhausted list's contribution as 0 for this column.
- Compute
column_sum = digit_one + digit_two + carry. - Append a new node with value
column_sum % 10; updatecarry = column_sum // 10. - Advance each non-null list pointer; return
dummy_head.next.
1class Solution:
2 def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
3 dummy_head = ListNode(0)
4 current = dummy_head
5 carry = 0
6
7 while l1 or l2 or carry:
8 digit_one = l1.val if l1 else 0 # treat exhausted list as contributing 0
9 digit_two = l2.val if l2 else 0
10
11 column_sum = digit_one + digit_two + carry
12 carry = column_sum // 10 # carry into the next column
13 current.next = ListNode(column_sum % 10)
14 current = current.next
15
16 if l1:
17 l1 = l1.next
18 if l2:
19 l2 = l2.next
20
21 return dummy_head.nextTime: O(max(m, n)) โ every node in both lists is visited exactly once, and the result has at most max(m, n) + 1 nodes.
Space: O(max(m, n)) โ the output list holds at most max(m, n) + 1 nodes; no extra auxiliary space beyond that.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Iterative digit simulation | O(max(m, n)) | O(max(m, n)) | Any linked-list addition; handles arbitrarily large numbers without integer overflow |
Common Mistakes
- Using
while l1 and l2as the loop condition โ this stops as soon as either list ends, silently discarding remaining digits from the longer list and any leftover carry. - Forgetting to append a node for the final carry โ if the last column sums to โฅ 10,
carry = 1remains after both lists are done; skipping it produces a result that is too short (e.g., 99 + 1 returns [0,0] instead of [0,0,1]). - Reusing input list nodes for output โ mutating
l1.valor redirectingl1.nextchanges the caller's data; always allocate freshListNodeobjects for the result. - Forgetting the dummy head โ without it you need a special case to initialize the result head, and the logic for the first node differs from all subsequent nodes.
- Advancing both pointers unconditionally โ calling
l1 = l1.nextwhenl1is alreadyNonecauses a null-pointer error; guard each advance with a null check.
Related Problems
Merge Two Sorted Listsโ same two-pointer linked-list traversal pattern, merging instead of summingAdd Binaryโ identical carry-based digit addition applied to binary strings instead of linked listsMultiply Stringsโ extends column-by-column arithmetic to multi-digit multiplication on string representationsReverse Linked Listโ foundational linked list pointer manipulation; a prerequisite skill for this problemPalindrome Linked Listโ linked list traversal with careful pointer bookkeeping, same null-check discipline required