Loading problems...
TL;DR: Iterate through both linked lists simultaneously, summing values node-by-node while maintaining a "carry" variable to construct a new result list.
The LeetCode 2 problem, titled Add Two Numbers, asks us to perform arithmetic addition on two non-negative integers. However, these integers are not provided as standard primitives; they are represented as linked lists where the digits are stored in reverse order. This means the head of the list represents the ones place, the second node represents the tens place, and so on. We must return the sum as a new linked list in the same reverse-order format.
This is a classic interview question that tests your ability to handle pointer manipulation and basic arithmetic state management simultaneously.
A naive approach to solving this problem attempts to convert the linked list representations directly into standard integer types, perform the addition, and then convert the result back into a linked list.
l1) to reconstruct the number it represents (e.g., 2 -> 4 -> 3 becomes 342).l2) to reconstruct its number.textfunction addTwoNumbers(l1, l2): num1 = convertListToNumber(l1) num2 = convertListToNumber(l2) sum = num1 + num2 return convertNumberToList(sum)
While logically sound for small inputs, this approach fails due to integer overflow. The constraints state that the number of nodes in each linked list can be up to 100. A number with 100 digits far exceeds the capacity of standard 64-bit integers (like long in Java or long long in C++). Even if the language supports arbitrary-precision integers (like Python or Java's BigInteger), converting the entire list to a number requires extra space and computation that ignores the structural advantage of the linked list format.
The key intuition for the optimal solution is to simulate the elementary school method of column addition. When we add numbers manually on paper, we align them by the least significant digit (the ones place) and add them column by column, carrying over any value that exceeds 9 to the next column.
Conveniently, the problem provides the lists in reverse order. This means the head of l1 and the head of l2 are already aligned at the least significant digit. We do not need to reverse the lists or use stacks to access the end of the numbers; we can simply traverse from the head.
The primary invariant we must maintain is the carry. At any given position, the value of the new node is determined by:
Visual Description: Imagine two pointers, one for each input list, moving rightward in lockstep. We also maintain a pointer for the result list. At each step, we pluck the values from the input pointers (treating null pointers as 0), add them to our current carry, and create a new node. The recursion or iteration "flows" from left to right, generating the output list directly. The process only terminates when both input lists are exhausted and the carry is zero.

dummyHead to a new node (0).current pointing to dummyHead.carry to 0.l1 != null OR l2 != null OR carry != 0:
x be l1.val if l1 exists, else 0.y be l2.val if l2 exists, else 0.total = x + y + carry.carry = total / 10 (integer division).total % 10.current.next.current to current.next.l1 exists, move l1 to l1.next.l2 exists, move l2 to l2.next.dummyHead.next.The algorithm guarantees correctness by strictly adhering to the mathematical definition of addition in base 10.
cpp/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) { ListNode* dummyHead = new ListNode(0); ListNode* current = dummyHead; int carry = 0; // Iterate while there are nodes to process or a carry remains while (l1 != nullptr || l2 != nullptr || carry != 0) { int x = (l1 != nullptr) ? l1->val : 0; int y = (l2 != nullptr) ? l2->val : 0; int sum = x + y + carry; carry = sum / 10; current->next = new ListNode(sum % 10); current = current->next; if (l1 != nullptr) l1 = l1->next; if (l2 != nullptr) l2 = l2->next; } return dummyHead->next; } };
java/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode dummyHead = new ListNode(0); ListNode current = dummyHead; int carry = 0; // Loop continues until both lists end and carry is resolved while (l1 != null || l2 != null || carry != 0) { int x = (l1 != null) ? l1.val : 0; int y = (l2 != null) ? l2.val : 0; int sum = x + y + carry; carry = sum / 10; current.next = new ListNode(sum % 10); current = current.next; if (l1 != null) l1 = l1.next; if (l2 != null) l2 = l2.next; } return dummyHead.next; } }
python# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]: dummy_head = ListNode(0) current = dummy_head carry = 0 # Continue if either list has nodes or there is a carry while l1 is not None or l2 is not None or carry != 0: x = l1.val if l1 is not None else 0 y = l2.val if l2 is not None else 0 total = x + y + carry carry = total // 10 current.next = ListNode(total % 10) current = current.next if l1 is not None: l1 = l1.next if l2 is not None: l2 = l2.next return dummy_head.next
Time Complexity: We iterate through the linked lists exactly once. The number of iterations is determined by the length of the longer list ( or ). If there is a carry at the end, we perform one extra operation, so the complexity is linear with respect to the input size.
Space Complexity: The space required is determined by the length of the new list we construct. The length of the result list is at most . Note that we do not count the input space, but we do count the space required for the output in this context. Auxiliary space (excluding output) is .
The Linked List - Addition of Numbers pattern used here is directly applicable to several other interview problems. Mastering the logic of simultaneous traversal and carry management allows you to solve:
Why do I get a NullPointerException or AttributeError?
l1.val or l2.val without checking if the node is null.if l1 != null before access.Why is my result missing the last digit (e.g., 5+5=0 instead of 10)?
l1 and l2 are null, ignoring the carry.Why does my solution Time Limit Exceed (TLE)?
l1 = l1.next) inside the loop.l1 != null remains permanently true.