Add Two Numbers medium
Problem Statement
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Example 1
Input: l1 = [2,4,3], l2 = [5,6,4] Output: [7,0,8] Explanation: 342 + 465 = 807.
Example 2
Input: l1 = [0], l2 = [0] Output: [0]
Example 3
Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9] Output: [8,9,9,9,0,0,0,1]
Steps
-
Initialization: Create a dummy node
head
to simplify the handling of the first node of the result list. Initialize acarry
variable to 0. Set a current nodecurrentNode
tohead
. -
Iteration: Iterate while either
l1
orl2
is not null, or thecarry
is not 0. -
Node Value Calculation: Get the values of the current nodes in
l1
andl2
(or 0 if a list is exhausted). Add these values and thecarry
to get thesum
. -
Digit Extraction and Carry Update: Extract the last digit of the
sum
(using the modulo operator%
) and create a new node with this digit. Updatecarry
by integer dividing thesum
by 10. -
Linking and Movement: Link the new node to the
currentNode
, and movecurrentNode
to the new node. Advancel1
andl2
to the next nodes if they are not null. -
Result: After the loop, return the next node after
head
(the actual head of the result list).
Explanation
The algorithm simulates manual addition of numbers. We iterate through the lists, adding digits along with any carry from the previous addition. The modulo operator helps us extract the last digit (the units place), while integer division updates the carry for the next addition. The dummy node simplifies the handling of the first node's creation.
Code
class ListNode {
val: number;
next: ListNode | null;
constructor(val?: number, next?: ListNode | null) {
this.val = (val===undefined ? 0 : val)
this.next = (next===undefined ? null : next)
}
}
function addTwoNumbers(l1: ListNode | null, l2: ListNode | null): ListNode | null {
const head = new ListNode(0); // Dummy node
let currentNode = head;
let carry = 0;
while (l1 !== null || l2 !== null || carry !== 0) {
const val1 = l1 ? l1.val : 0;
const val2 = l2 ? l2.val : 0;
const sum = val1 + val2 + carry;
const digit = sum % 10;
carry = Math.floor(sum / 10);
currentNode.next = new ListNode(digit);
currentNode = currentNode.next;
l1 = l1 ? l1.next : null;
l2 = l2 ? l2.next : null;
}
return head.next;
}
// Example usage:
const l1 = new ListNode(2, new ListNode(4, new ListNode(3)));
const l2 = new ListNode(5, new ListNode(6, new ListNode(4)));
const result = addTwoNumbers(l1, l2);
let current = result;
let output = "";
while(current){
output += current.val + " ";
current = current.next;
}
console.log(output); // Output: 7 0 8
Complexity
- Time Complexity: O(max(m, n)), where 'm' and 'n' are the lengths of the input linked lists. We iterate through the lists at most once.
- Space Complexity: O(max(m, n)), in the worst case, the resulting linked list has a length equal to the maximum length of the input lists plus one (for the carry). This is because we are creating new nodes for the result list.