Before attempting this problem, you should be comfortable with:
Linked Lists - Traversing, reversing, and building linked lists
Stacks - Using LIFO property to reverse order of elements
Carry Propagation - How carry works when adding numbers digit by digit
1. Reverse List
Intuition
When adding two numbers, we naturally start from the least significant digit. The problem gives us numbers stored with the most significant digit first, so reversing both lists makes the addition straightforward.
After reversing, we can walk through both lists simultaneously, adding corresponding digits along with any carry. We build the result by prepending each new digit to our answer, which naturally produces the correct order without needing another reversal at the end.
Algorithm
Reverse both linked lists l1 and l2.
Initialize head = null and carry = 0.
While either list has nodes remaining or carry > 0:
Get the values v1 and v2 from the current nodes (use 0 if a list is exhausted).
Compute total = v1 + v2 + carry.
Create a new node with value total % 10 and prepend it to head.
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/funcaddTwoNumbers(l1 *ListNode, l2 *ListNode)*ListNode {
reverseList :=func(head *ListNode)*ListNode {var prev *ListNode
curr := head
for curr !=nil{
temp := curr.Next
curr.Next = prev
prev = curr
curr = temp
}return prev
}
l1 =reverseList(l1)
l2 =reverseList(l2)var head *ListNode
carry :=0for l1 !=nil|| l2 !=nil|| carry >0{
v1, v2 :=0,0if l1 !=nil{
v1 = l1.Val
l1 = l1.Next
}if l2 !=nil{
v2 = l2.Val
l2 = l2.Next
}
total := v1 + v2 + carry
carry = total /10
node :=&ListNode{Val: total %10, Next: head}
head = node
}return head
}
/**
* Example:
* var li = ListNode(5)
* var v = li.`val`
* Definition for singly-linked list.
* class ListNode(var `val`: Int) {
* var next: ListNode? = null
* }
*/class Solution {privatefunreverseList(head: ListNode?): ListNode?{var prev: ListNode?=nullvar curr = head
while(curr !=null){val temp = curr.next
curr.next = prev
prev = curr
curr = temp
}return prev
}funaddTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode?{var list1 =reverseList(l1)var list2 =reverseList(l2)var head: ListNode?=nullvar carry =0while(list1 !=null|| list2 !=null|| carry >0){val v1 = list1?.`val` ?:0val v2 = list2?.`val` ?:0val total = v1 + v2 + carry
carry = total /10val node =ListNode(total %10)
node.next = head
head = node
list1 = list1?.next
list2 = list2?.next
}return head
}}
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init() { self.val = 0; self.next = nil; }
* public init(_ val: Int) { self.val = val; self.next = nil; }
* public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
* }
*/classSolution{privatefuncreverseList(_ head:ListNode?)->ListNode?{var prev:ListNode?=nilvar curr = head
while curr !=nil{let temp = curr?.next
curr?.next = prev
prev = curr
curr = temp
}return prev
}funcaddTwoNumbers(_ l1:ListNode?,_ l2:ListNode?)->ListNode?{var l1 =reverseList(l1)var l2 =reverseList(l2)var head:ListNode?=nilvar carry =0while l1 !=nil|| l2 !=nil|| carry >0{let v1 = l1?.val ??0let v2 = l2?.val ??0let total = v1 + v2 + carry
carry = total /10let node =ListNode(total %10)
node.next = head
head = node
l1 = l1?.next
l2 = l2?.next
}return head
}}
Time & Space Complexity
Time complexity: O(m+n)
Space complexity: O(max(m,n)) for the output list.
Where m is the length of l1 and n is the length of l2.
2. Stack
Intuition
If we want to avoid modifying the input lists, we can use stacks to reverse the digit order implicitly. Pushing all digits onto stacks gives us access to them in reverse order when we pop.
This approach preserves the original lists while still allowing us to process digits from least significant to most significant. The rest of the logic is identical: add digits with carry and build the result by prepending nodes.
Algorithm
Push all values from l1 onto stack s1 and all values from l2 onto stack s2.
Initialize head = null and carry = 0.
While either stack is non-empty or carry > 0:
Pop values from s1 and s2 (use 0 if a stack is empty).
Compute total = v1 + v2 + carry.
Create a new node with value total % 10 and prepend it to head.
/**
* Definition for singly-linked list.
* public class ListNode {
* public int val;
* public ListNode next;
* public ListNode(int val=0, ListNode next=null) {
* this.val = val;
* this.next = next;
* }
* }
*/publicclassSolution{publicListNodeAddTwoNumbers(ListNode l1,ListNode l2){Stack<int> s1 =newStack<int>();Stack<int> s2 =newStack<int>();while(l1 !=null){
s1.Push(l1.val);
l1 = l1.next;}while(l2 !=null){
s2.Push(l2.val);
l2 = l2.next;}int carry =0;ListNode head =null;while(s1.Count >0|| s2.Count >0|| carry >0){int v1 = s1.Count >0? s1.Pop():0;int v2 = s2.Count >0? s2.Pop():0;int total = v1 + v2 + carry;
carry = total /10;ListNode node =newListNode(total %10);
node.next = head;
head = node;}return head;}}
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/funcaddTwoNumbers(l1 *ListNode, l2 *ListNode)*ListNode {
s1 :=[]int{}
s2 :=[]int{}for l1 !=nil{
s1 =append(s1, l1.Val)
l1 = l1.Next
}for l2 !=nil{
s2 =append(s2, l2.Val)
l2 = l2.Next
}
carry :=0var head *ListNode
forlen(s1)>0||len(s2)>0|| carry >0{
v1, v2 :=0,0iflen(s1)>0{
v1 = s1[len(s1)-1]
s1 = s1[:len(s1)-1]}iflen(s2)>0{
v2 = s2[len(s2)-1]
s2 = s2[:len(s2)-1]}
total := v1 + v2 + carry
carry = total /10
node :=&ListNode{Val: total %10, Next: head}
head = node
}return head
}
/**
* Example:
* var li = ListNode(5)
* var v = li.`val`
* Definition for singly-linked list.
* class ListNode(var `val`: Int) {
* var next: ListNode? = null
* }
*/class Solution {funaddTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode?{val s1 = ArrayDeque<Int>()val s2 = ArrayDeque<Int>()var curr1 = l1
while(curr1 !=null){
s1.addLast(curr1.`val`)
curr1 = curr1.next
}var curr2 = l2
while(curr2 !=null){
s2.addLast(curr2.`val`)
curr2 = curr2.next
}var carry =0var head: ListNode?=nullwhile(s1.isNotEmpty()|| s2.isNotEmpty()|| carry >0){val v1 =if(s1.isNotEmpty()) s1.removeLast()else0val v2 =if(s2.isNotEmpty()) s2.removeLast()else0val total = v1 + v2 + carry
carry = total /10val node =ListNode(total %10)
node.next = head
head = node
}return head
}}
/**
* Definition for singly-linked list.
* public class ListNode {
* public var val: Int
* public var next: ListNode?
* public init() { self.val = 0; self.next = nil; }
* public init(_ val: Int) { self.val = val; self.next = nil; }
* public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
* }
*/classSolution{funcaddTwoNumbers(_ l1:ListNode?,_ l2:ListNode?)->ListNode?{var s1 =[Int]()var s2 =[Int]()var curr1 = l1
while curr1 !=nil{
s1.append(curr1!.val)
curr1 = curr1?.next
}var curr2 = l2
while curr2 !=nil{
s2.append(curr2!.val)
curr2 = curr2?.next
}var carry =0var head:ListNode?=nilwhile!s1.isEmpty ||!s2.isEmpty || carry >0{let v1 = s1.isEmpty ?0: s1.removeLast()let v2 = s2.isEmpty ?0: s2.removeLast()let total = v1 + v2 + carry
carry = total /10let node =ListNode(total %10)
node.next = head
head = node
}return head
}}
Time & Space Complexity
Time complexity: O(m+n)
Space complexity: O(m+n)
Where m is the length of l1 and n is the length of l2.
Common Pitfalls
Adding Digits from Head Instead of Tail
Unlike the basic "Add Two Numbers" problem, the digits here are stored most-significant-digit first. Trying to add digits directly from the head without reversing or using a stack produces wrong results since you are adding the wrong place values together.
# Wrong: adding from head directlywhile l1 and l2:
total = l1.val + l2.val # Misaligned place values
Forgetting to Handle Lists of Different Lengths
When lists have different lengths, the shorter list needs to be padded conceptually with leading zeros. Failing to align the lists properly before addition causes incorrect results.
# Wrong: assuming lists are same lengthwhile l1 and l2:# Stops early when one list ends# ...
Building Result in Wrong Order
After computing digits from least to most significant, the result must be constructed so that the most significant digit is at the head. Appending to the tail instead of prepending creates a reversed result.
# Wrong: appending to tail
result.next= ListNode(digit)# Should prepend: node.next = head; head = node