Add Two Numbers Represented as Linked List in DSA C++ - Time & Space Complexity
We want to know how the time to add two numbers stored as linked lists grows as the numbers get longer.
How does the number of steps change when the linked lists have more digits?
Analyze the time complexity of the following code snippet.
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(0);
ListNode* current = dummy;
int carry = 0;
while (l1 || l2 || carry) {
int sum = carry;
if (l1) { sum += l1->val; l1 = l1->next; }
if (l2) { sum += l2->val; l2 = l2->next; }
carry = sum / 10;
current->next = new ListNode(sum % 10);
current = current->next;
}
return dummy->next;
}
This code adds two numbers digit by digit, stored in linked lists, and returns the sum as a new linked list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that goes through each node of both linked lists.
- How many times: It runs once for each digit in the longer linked list, plus one extra if there is a carry at the end.
As the number of digits (nodes) increases, the number of steps grows roughly the same amount.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 steps |
| 100 | About 100 steps |
| 1000 | About 1000 steps |
Pattern observation: The time grows linearly with the number of digits.
Time Complexity: O(n)
This means the time to add the numbers grows directly in proportion to the number of digits.
[X] Wrong: "The time complexity is O(n²) because we create new nodes inside the loop."
[OK] Correct: Creating a new node each time is a constant time operation, done once per digit, so it does not multiply the steps; the loop still runs only once per digit.
Understanding this linear time complexity helps you explain how your solution scales with input size, a key skill in interviews.
"What if the digits were stored in forward order instead of reverse? How would the time complexity change?"
Practice
Solution
Step 1: Understand the problem context
The problem involves two linked lists where each node contains a single digit of a number, stored in reverse order.Step 2: Identify the required operation
We need to add these two numbers digit by digit, handling carry, and return the sum as a linked list.Final Answer:
Adding two numbers where each digit is stored in a node of a linked list -> Option AQuick Check:
Adding digits in linked lists = Adding two numbers where each digit is stored in a node of a linked list [OK]
- Confusing addition with sorting
- Thinking the problem is about reversing lists
- Assuming the digits are stored in normal order
Solution
Step 1: Check pointer usage in struct
Node* next is correct to point to the next node; struct Node { int val; Node next; Node(int x) : val(x), next(nullptr) {} }; uses Node next which is incorrect (causes infinite recursion).Step 2: Check constructor initialization
struct Node { int val; Node* next; Node(int x) : val(x), next(nullptr) {} }; uses member initializer list correctly with nullptr; struct Node { int val; Node* next; Node(int x) { val = x; next = NULL; } }; uses assignment inside constructor body which is valid but less modern; struct Node { int val; Node* next; Node(int x) : val(x), next(NULL) {} }; uses NULL which is legacy.Final Answer:
struct Node { int val; Node* next; Node(int x) : val(x), next(nullptr) {} }; -> Option CQuick Check:
Use pointer and nullptr in constructor [OK]
- Using Node next instead of Node* next
- Using NULL instead of nullptr
- Not initializing next pointer
Solution
Step 1: Add digits node by node with carry
2+5=7 (carry 0), 4+6=10 (carry 1), 3+4+1=8 (carry 0)Step 2: Form the resulting linked list
Digits are 7, 0 (from 10 carry), 8 so list is 7 -> 0 -> 8 -> nullFinal Answer:
7 -> 0 -> 8 -> null -> Option BQuick Check:
342 + 465 = 807 represented as 7->0->8 [OK]
- Not handling carry correctly
- Adding digits in wrong order
- Confusing node values with actual numbers
Node* addTwoNumbers(Node* l1, Node* l2) {
Node* dummy = new Node(0);
Node* current = dummy;
int carry = 0;
while (l1 != nullptr && l2 != nullptr) {
int sum = l1->val + l2->val + carry;
carry = sum / 10;
current->next = new Node(sum % 10);
current = current->next;
l1 = l1->next;
l2 = l2->next;
}
return dummy->next;
}Solution
Step 1: Analyze loop condition
The loop runs only while both l1 and l2 are not null, so it stops early if one list is longer.Step 2: Correct loop condition
It should continue while either l1 or l2 has nodes to process all digits, so use || instead of &&.Final Answer:
The loop condition should be while (l1 != nullptr || l2 != nullptr) -> Option AQuick Check:
Use || to handle different length lists [OK]
- Using && causes missing nodes in longer list
- Ignoring carry after loop ends
- Not advancing pointers correctly
Solution
Step 1: Understand carry after full addition
After adding all nodes, if carry is still 1, it means the sum has an extra digit.Step 2: Add new node for carry
To represent this extra digit, create a new node with carry value and link it at the end.Final Answer:
Add a new node with the carry value at the end of the result list -> Option DQuick Check:
Carry leftover means add new node [OK]
- Ignoring leftover carry causing wrong sum
- Trying to subtract carry instead of adding node
- Restarting addition unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
