Add Two Numbers Represented as Linked List in DSA Java - 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 work change when the lists have more digits?
Analyze the time complexity of the following code snippet.
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode current = dummy;
int carry = 0;
while (l1 != null || l2 != null || carry != 0) {
int sum = carry;
if (l1 != null) { sum += l1.val; l1 = l1.next; }
if (l2 != null) { 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, handling carry, and creates a new linked list for the result.
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 list, plus one extra if there is a carry at the end.
As the number of digits (nodes) increases, the loop runs more times, roughly once per digit.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 loop cycles |
| 100 | About 100 loop cycles |
| 1000 | About 1000 loop cycles |
Pattern observation: The work grows directly with the number of digits; doubling digits doubles the work.
Time Complexity: O(n)
This means the time to add the numbers grows linearly with the number of digits.
[X] Wrong: "The time depends on the sum of the numbers, not their length."
[OK] Correct: The code processes each digit once, so time depends on the number of digits, not the value of the numbers.
Understanding this helps you explain how to handle linked lists and carry in addition, a common coding challenge skill.
"What if the input lists were doubly linked lists? 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 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 digits node by node from two linked lists representing numbers -> Option DQuick Check:
Adding digits node by node = D [OK]
- Confusing addition with sorting
- Ignoring carry during addition
- Assuming numbers are stored in forward order
Solution
Step 1: Recall Java object creation syntax
In Java, to create a new object, use the 'new' keyword followed by the constructor call with parameters.Step 2: Check each option for correct syntax
ListNode node = new ListNode(5); uses 'new ListNode(5);' which is correct. ListNode node = ListNode(5); misses 'new'. ListNode node = new ListNode(); node.next = 5; incorrectly sets next instead of val. ListNode node = new ListNode.val(5); is invalid syntax.Final Answer:
ListNode node = new ListNode(5); -> Option CQuick Check:
Java new object syntax = B [OK]
- Omitting 'new' keyword
- Incorrect constructor call syntax
- Trying to call constructor like a method without 'new'
- Confusing node.val and node.next
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode p = l1, q = l2, curr = dummy;
int carry = 0;
while (p != null || q != null) {
int x = (p != null) ? p.val : 0;
int y = (q != null) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
if (p != null) p = p.next;
if (q != null) q = q.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummy.next;
}Solution
Step 1: Add digits node by node with carry
Adding 2+5=7 (carry 0), 4+6=10 (carry 1), 3+4=7 plus carry 1 = 8.Step 2: Construct the resulting linked list
Digits are 7 (units), 0 (tens), 8 (hundreds), so linked list is 7 -> 0 -> 8 -> null.Final Answer:
7 -> 0 -> 8 -> null -> Option AQuick Check:
342 + 465 = 807 represented as 7->0->8 [OK]
- Ignoring carry in addition
- Appending nodes incorrectly
- Mixing digit order in output
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
int carry = 0;
while (l1 != null && l2 != null) {
int sum = carry + l1.val + l2.val;
carry = sum / 10;
curr.next = new ListNode(sum % 10);
curr = curr.next;
l1 = l1.next;
l2 = l2.next;
}
if (carry > 0) {
curr.next = new ListNode(carry);
}
return dummy.next;
}Solution
Step 1: Analyze the loop condition
The loop uses '&&' which stops when either list ends, missing remaining nodes of longer list.Step 2: Correct loop condition to '||'
Using '||' ensures the loop continues until both lists are fully processed, handling different lengths correctly.Final Answer:
The while loop should use '||' instead of '&&' to handle different length lists -> Option BQuick Check:
Loop condition must cover all nodes = A [OK]
- Using '&&' causing early loop exit
- Not handling carry after loop
- Not advancing pointers correctly
Solution
Step 1: Consider memory constraints with large inputs
Converting to integers or arrays requires large memory, not feasible for millions of nodes.Step 2: Use iterative addition with constant extra space
Process nodes one by one, create result nodes on the fly, and avoid storing entire numbers in memory.Final Answer:
Use iterative addition with constant extra space and process nodes one by one -> Option AQuick Check:
Iterative node-wise addition saves memory = C [OK]
- Trying to convert entire list to integer causing overflow
- Using extra arrays increasing memory usage
- Reversing lists unnecessarily increasing complexity
Ready to prove it?
Pass the test and this pattern moves unknown
