title: Add Two Numbers II slug: add-two-numbers-ii difficulty: medium leetcode_id: 445 leetcode_url: https://leetcode.com/problems/add-two-numbers-ii/ categories: - linked-lists - stack - math patterns: - slug: linkedlist-reversal is_optimal: true function_signature: "def add_two_numbers(l1: ListNode, l2: ListNode) -> ListNode:" test_cases: visible: - input: { l1: [7, 2, 4, 3], l2: [5, 6, 4] } expected: [7, 8, 0, 7] - input: { l1: [2, 4, 3], l2: [5, 6, 4] } expected: [8, 0, 7] - input: { l1: [0], l2: [0] } expected: [0] hidden: - input: { l1: [9, 9, 9], l2: [1] } expected: [1, 0, 0, 0] - input: { l1: [5], l2: [5] } expected: [1, 0] - input: { l1: [1, 2, 3, 4, 5], l2: [6, 7, 8, 9] } expected: [1, 9, 1, 3, 4] - input: { l1: [9, 9, 9, 9, 9], l2: [9, 9, 9, 9, 9] } expected: [1, 9, 9, 9, 9, 8] - input: { l1: [1], l2: [9, 9, 9, 9] } expected: [1, 0, 0, 0, 0] description: | You are given two **non-empty** linked lists representing two non-negative integers. The most significant digit comes first 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. constraints: | - `1 <= number of nodes in each list <= 100` - `0 <= Node.val <= 9` - The list represents a number without leading zeros examples: - input: "l1 = [7,2,4,3], l2 = [5,6,4]" output: "[7,8,0,7]" explanation: "7243 + 564 = 7807" - input: "l1 = [2,4,3], l2 = [5,6,4]" output: "[8,0,7]" explanation: "243 + 564 = 807" - input: "l1 = [0], l2 = [0]" output: "[0]" explanation: "0 + 0 = 0" explanation: intuition: | Think of this problem like adding two numbers by hand on paper. When you add numbers manually, you start from the **rightmost digit** (the least significant) and work your way left, carrying over when a column sums to 10 or more. The challenge here is that linked lists give us digits in the **opposite order** — most significant digit first. It's like being handed two numbers written left-to-right and being asked to add them without being able to peek at the end. There are two main ways to handle this: 1. **Reverse the lists** — Convert the problem into "Add Two Numbers" (LeetCode 2), where digits are already in least-significant-first order. Add them, then reverse the result. 2. **Use stacks** — Push all digits onto stacks, then pop them off (which gives us least-significant-first order naturally). This avoids modifying the input lists. Both approaches transform the problem into one where we process digits from right to left, just like manual addition. approach: | We'll use the **Stack Approach** to solve this without modifying the input lists: **Step 1: Push all digits onto stacks** - Create two stacks, one for each linked list - Traverse each list and push every value onto its respective stack - After this step, the top of each stack holds the least significant digit   **Step 2: Add digits with carry** - Initialise `carry` to `0` and `result` pointer to `None` - While either stack has elements OR there's a carry: - Pop from stack 1 if not empty, otherwise use `0` - Pop from stack 2 if not empty, otherwise use `0` - Calculate `total = val1 + val2 + carry` - The digit for this position is `total % 10` - The new carry is `total // 10` - Create a new node with this digit and prepend it to the result   **Step 3: Build result by prepending** - Each new node becomes the new head of our result list - This naturally builds the list in most-significant-first order - Return the head of the result list   This approach mirrors how we add numbers by hand, processing from right to left while propagating carries. common_pitfalls: - title: Forgetting the Final Carry description: | After processing all digits from both numbers, there might still be a carry left over. For example, adding `[9,9]` and `[1]` gives `99 + 1 = 100`. If you exit the loop when both stacks are empty but don't check for a remaining carry, you'll return `[0,0]` instead of `[1,0,0]`. Always continue the loop while `carry > 0`, or handle the final carry after the main loop. wrong_approach: "Exit loop when both stacks are empty" correct_approach: "Continue while stacks have elements OR carry is non-zero" - title: Building the Result List Backwards description: | Since we process digits from least significant to most significant, we need to build the result list in reverse order. If you append nodes to the end, you'll get the digits reversed. For example, adding `[2,4,3]` and `[5,6,4]`: - Process: 3+4=7, 4+6=10 (carry 1), 2+5+1=8 - Appending gives: `[7,0,8]` (wrong!) - Prepending gives: `[8,0,7]` (correct!) wrong_approach: "Append new nodes to the tail of result" correct_approach: "Prepend new nodes to the head of result" - title: Modifying Input Lists description: | While reversing the input lists works, the problem may expect you to leave them unchanged (especially in production code where the lists might be used elsewhere). The stack approach naturally avoids this issue since we only read from the lists, never modify them. If you do use the reversal approach, consider reversing the lists back to their original state before returning. wrong_approach: "Reverse input lists in place without restoring" correct_approach: "Use stacks, or reverse and restore the input lists" key_takeaways: - "**Stacks reverse order naturally**: When processing order matters, stacks can transform first-to-last into last-to-first without modifying the original data" - "**Prepending builds lists in reverse**: To construct a list from least to most significant, prepend each new node as the head" - "**Handle carries beyond input length**: The result can have more digits than either input (e.g., `999 + 1 = 1000`)" - "**Related problem**: 'Add Two Numbers' (LeetCode 2) is the reverse version where least significant digit comes first" time_complexity: "O(n + m). We traverse both lists once to fill the stacks, then process at most `max(n, m) + 1` digits during addition." space_complexity: "O(n + m). The stacks store all digits from both input lists, plus the result list of similar size." solutions: - approach_name: Stack-Based Addition is_optimal: true code: | class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def add_two_numbers(l1: ListNode, l2: ListNode) -> ListNode: # Push all digits onto stacks stack1, stack2 = [], [] while l1: stack1.append(l1.val) l1 = l1.next while l2: stack2.append(l2.val) l2 = l2.next carry = 0 result = None # Process digits from least to most significant while stack1 or stack2 or carry: # Get digits (0 if stack is empty) val1 = stack1.pop() if stack1 else 0 val2 = stack2.pop() if stack2 else 0 # Add with carry total = val1 + val2 + carry digit = total % 10 carry = total // 10 # Prepend new node to result new_node = ListNode(digit) new_node.next = result result = new_node return result explanation: | **Time Complexity:** O(n + m) — We traverse each list once to build stacks, then process each digit once. **Space Complexity:** O(n + m) — Stacks hold all digits from both lists. The stack approach elegantly handles the digit ordering problem without modifying input lists. By popping from stacks, we naturally get digits in right-to-left order for addition. - approach_name: Reverse Lists is_optimal: false code: | class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def add_two_numbers(l1: ListNode, l2: ListNode) -> ListNode: def reverse(head): """Reverse a linked list in place.""" prev = None while head: next_node = head.next head.next = prev prev = head head = next_node return prev # Reverse both lists to get least significant digit first l1 = reverse(l1) l2 = reverse(l2) carry = 0 dummy = ListNode(0) current = dummy # Add digits from least to most significant while l1 or l2 or carry: val1 = l1.val if l1 else 0 val2 = l2.val if l2 else 0 total = val1 + val2 + carry digit = total % 10 carry = total // 10 current.next = ListNode(digit) current = current.next if l1: l1 = l1.next if l2: l2 = l2.next # Reverse result to get most significant digit first return reverse(dummy.next) explanation: | **Time Complexity:** O(n + m) — Three passes: reverse l1, reverse l2, reverse result. **Space Complexity:** O(1) extra — Only uses pointers (result list doesn't count as extra space). This approach converts the problem to the simpler "Add Two Numbers" variant by reversing the inputs. The tradeoff is that it modifies the input lists (which may or may not be acceptable depending on requirements).