Lesson 42 of 164
Add Two Numbers Represented as Linked Lists
Two non-empty linked lists represent two non-negative integers. The digits are stored in reverse order, one digit per node, so the head is the ones digit. Add the numbers and return the sum as a list in the same format.
LeetCode: 2. Add Two Numbers
Example
Input: (1 -> 8 -> 2) + (3 -> 6 -> 5) Output: 4 -> 4 -> 8 (281 + 563 = 844)
Input: (4 -> 8 -> 1) + (3 -> 6) Output: 7 -> 4 -> 2 (184 + 63 = 247)Brute force: convert to integers
Read each list into a number, add them, and write the sum back out digit by digit.
import java.util.ArrayList;
import java.util.List;
public class Main {
static class ListNode {
int val;
ListNode next;
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
static ListNode fromArray(int... values) {
ListNode head = null;
for (int i = values.length - 1; i >= 0; i--) {
head = new ListNode(values[i], head);
}
return head;
}
static List<Integer> toList(ListNode list) {
List<Integer> values = new ArrayList<>();
for (ListNode node = list; node != null; node = node.next) {
values.add(node.val);
}
return values;
}
static long toNumber(ListNode list) {
long number = 0, place = 1;
for (ListNode node = list; node != null; node = node.next) {
number += node.val * place;
place *= 10; // wraps silently on overflow
}
return number;
}
static ListNode fromNumber(long n) {
List<Integer> digits = new ArrayList<>();
do {
digits.add((int) (n % 10));
n /= 10;
} while (n != 0);
ListNode head = null;
for (int i = digits.size() - 1; i >= 0; i--) {
head = new ListNode(digits.get(i), head);
}
return head;
}
static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return fromNumber(toNumber(l1) + toNumber(l2));
}
public static void main(String[] args) {
System.out.println(toList(addTwoNumbers(fromArray(1, 8, 2), fromArray(3, 6, 5))));
System.out.println(toList(addTwoNumbers(fromArray(4, 8, 1), fromArray(3, 6))));
}
}[4, 4, 8]
[7, 4, 2]Time: O(m + n). Space: O(max(m, n)) for the result.
This only works while the numbers fit in a long, which holds 18 full digits. LeetCode's lists can have 100 digits, and place *= 10 overflows long before that. Java long arithmetic wraps silently, so the result would be wrong without any error.
Optimal: add digit by digit
Add the lists the way you add on paper: the ones digits first, then the tens, carrying 1 whenever a column reaches 10. The reversed order means the lists are already in the right order for that. Keep going while either list has digits or a carry is left over.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Main {
static class ListNode {
int val;
ListNode next;
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
static ListNode fromArray(int... values) {
ListNode head = null;
for (int i = values.length - 1; i >= 0; i--) {
head = new ListNode(values[i], head);
}
return head;
}
static List<Integer> toList(ListNode list) {
List<Integer> values = new ArrayList<>();
for (ListNode node = list; node != null; node = node.next) {
values.add(node.val);
}
return values;
}
static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0, null);
ListNode tail = dummy;
int carry = 0;
while (l1 != null || l2 != null || carry > 0) {
int sum = carry + (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val);
carry = sum / 10;
tail.next = new ListNode(sum % 10, null);
tail = tail.next;
if (l1 != null) l1 = l1.next;
if (l2 != null) l2 = l2.next;
}
return dummy.next;
}
public static void main(String[] args) {
System.out.println(toList(addTwoNumbers(fromArray(1, 8, 2), fromArray(3, 6, 5))));
System.out.println(toList(addTwoNumbers(fromArray(4, 8, 1), fromArray(3, 6))));
System.out.println(toList(addTwoNumbers(fromArray(9, 9, 9), fromArray(1))));
int[] big = new int[30];
Arrays.fill(big, 9);
System.out.println(toList(addTwoNumbers(fromArray(big), fromArray(1))).size());
}
}[4, 4, 8]
[7, 4, 2]
[0, 0, 0, 1]
31Time: O(max(m, n)). Space: O(max(m, n)) for the result, O(1) besides it.
The loop only advances the parameters l1 and l2 and never changes a node, so the inputs stay intact and the result is a fresh list. List nodes use null for "no next node" and have mutable fields. A dummy node gives tail somewhere to start, which avoids a special case for the first digit.
Edge cases
- Different lengths: a finished list contributes
0. - Final carry:
999 + 1needs a new node for the leading1. - Digits stored most significant first (LeetCode 445): reverse both lists, add, and reverse the result, or push the digits onto two stacks first.
