Unleash Your Inner Mathematician: Adding Numbers with Linked Lists (LeetCode #2)
Hey awesome developers! 👋 Ever wondered how computers perform basic arithmetic with a twist? Today, we're diving into a classic LeetCode problem that might seem simple on the surface but introduces some fundamental data structures and algorithmic thinking: "Add Two Numbers".
This problem is a fantastic way to sharpen your skills with linked lists and understand how to simulate everyday operations like addition programmatically. Don't worry if linked lists sound intimidating; we'll break it down piece by piece!
📚 Problem Explanation: Digits in Reverse!
Imagine you have two numbers, but instead of seeing them as regular integers like 342 or 465, their digits are stored in a special way: a linked list, and in reverse order!
Each "node" in our linked list holds a single digit. For example:
- The number
342would be represented as a linked list:2 -> 4 -> 3 - The number
465would be:5 -> 6 -> 4
Our mission? To add these two numbers together, digit by digit, and return their sum as another linked list, also in reverse order.
Let's look at Example 1:
- Input:
l1 = [2,4,3](represents 342) - Input:
l2 = [5,6,4](represents 465) - Output:
[7,0,8](represents 807)
See? 342 + 465 = 807. The [7,0,8] linked list correctly gives us 807 in reverse!
A few important rules:
- The lists are non-empty.
- Digits are non-negative (0-9).
- No leading zeros (unless the number itself is 0, like
[0]).
🤔 Intuition: How Do We Add Numbers By Hand?
Before we jump into code, let's think about how you add numbers manually:
342
+ 465
-----
- Start from the rightmost digits:
2 + 5 = 7. Write down7. - Move to the next digits (tens place):
4 + 6 = 10. Write down0, and carry over1to the hundreds place. - Move to the next digits (hundreds place):
3 + 4 + (the carried-over 1) = 8. Write down8.
The result is 807.
This "digit-by-digit, with a carry-over" strategy is exactly what we'll replicate with our linked lists! Since the digits are already in reverse order, it's like we're already starting from the rightmost digit (the units place)! This is a huge hint.
🪜 Approach: Step-by-Step with Linked Lists
Our approach will mimic manual addition:
-
Initialize:
- Create a
dummynode. This is a common trick in linked list problems. It acts as a placeholder for the head of our new list. We'll eventually returndummy.next. - Create a
currentpointer, initialized todummy. This pointer will help us build our result list by moving forward. - Initialize a
carryvariable to0. This will store any carry-over from the previous sum.
- Create a
Iterate through the lists: We need to keep adding digits as long as there are digits in either
l1orl2, or if there's still acarryleft over from a previous addition. Thiswhileloop condition is crucial:while l1 or l2 or carry:-
Calculate the sum for the current position:
- Start
total_sumwith thecarryfrom the previous step. - If
l1is notNone(meaning there's a digit in the first number), addl1.valtototal_sumand movel1to its next node (l1 = l1.next). - If
l2is notNone(meaning there's a digit in the second number), addl2.valtototal_sumand movel2to its next node (l2 = l2.next).
- Start
-
Determine the current digit and new carry:
- The digit for our result list at the current position will be
total_sum % 10(the remainder after dividing by 10). - The new
carrywill betotal_sum // 10(the integer division by 10).
- The digit for our result list at the current position will be
-
Build the result list:
- Create a new
ListNodewith the calculateddigit. - Append this new node to our result list:
current.next = new_node. - Move
currentforward to this new node:current = current.next.
- Create a new
Return: Once the loop finishes, we've built our entire sum list. Return
dummy.nextto get the actual head of the sum list (skipping the initial placeholderdummynode).
This process continues until both input lists are exhausted AND there's no carry left.
💻 Code: Bringing It to Life (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]:
# Create a dummy node to simplify handling the head of the result list
dummy_head = ListNode()
# 'current' pointer will build our new linked list
current = dummy_head
# Initialize carry to 0
carry = 0
# Loop as long as there are digits in either list or a carry exists
while l1 or l2 or carry:
# Get the value from l1 (or 0 if l1 is exhausted)
val1 = l1.val if l1 else 0
# Get the value from l2 (or 0 if l2 is exhausted)
val2 = l2.val if l2 else 0
# Calculate the total sum for the current position
total_sum = val1 + val2 + carry
# Determine the digit for the new node (units place of total_sum)
digit = total_sum % 10
# Determine the new carry (tens place of total_sum)
carry = total_sum // 10
# Create a new node with the calculated digit
current.next = ListNode(digit)
# Move our 'current' pointer forward to the new node
current = current.next
# Move l1 and l2 pointers forward if they are not exhausted
if l1:
l1 = l1.next
if l2:
l2 = l2.next
# The first node (dummy_head) was just a placeholder.
# The actual result list starts from dummy_head.next.
return dummy_head.next
⏱️ Time & Space Complexity Analysis
Time Complexity: O(max(m, n))
-
mis the number of nodes inl1. -
nis the number of nodes inl2. - We iterate through both linked lists exactly once. The loop runs for a number of times proportional to the length of the longer list. This makes the time complexity linear with respect to the length of the longer input list.
Space Complexity: O(max(m, n))
- In the worst-case scenario, the resulting linked list can have
max(m, n) + 1nodes (if there's a final carry-over). We are creating a new linked list to store the sum. Therefore, the space complexity is also linear with respect to the length of the longer input list.
🌟 Key Takeaways
- Linked Lists for Arithmetic: This problem beautifully demonstrates how linked lists can be used to represent and manipulate numbers, especially useful when dealing with very large numbers that might exceed standard integer types.
- The "Dummy Node" Trick: Using a
dummy_headnode is a super common and effective pattern in linked list problems. It simplifies code by always having a node to attach to, eliminating special checks for an empty result list or when adding the very first node. - Carry Handling: Understanding how to manage the
carrydigit is fundamental to correctly implementing addition, whether manually or programmatically. - Simulating Manual Processes: Many algorithmic problems can be solved by breaking them down into steps that mimic how we would solve them in real life.
This problem is a fantastic stepping stone for more complex linked list manipulations and numerical algorithms. Keep practicing, and you'll be a LeetCode master in no time! Happy coding!
Submission Details:
Author Account: p1Hzd8mRM8
Time Published: 2026-05-16 22:27:48
Top comments (0)