Topics › Linked List › Medium Problems of LL
Add one to a number represented by LL
LeetCode ↗ Java source ↗ Edit this article ↗
Jump to code:
Problem
A non-negative integer is stored in a singly linked list, one decimal digit per node, with the most significant digit at the head. Add one to the number and return the head of the resulting list. The input has no leading zeros except for the number 0 itself. If the input list is empty we treat it as the number 0, so the answer is a single node holding 1.
Constraints: 1 ≤ n ≤ 10^5 digits, each 0 ≤ val ≤ 9. The number can have far more digits than fit in a long, so converting the whole list to an integer is not an option.
Example 1
head = 1 -> 2 -> 3
answer = 1 -> 2 -> 4 // 123 + 1 = 124
Example 2
head = 9 -> 9 -> 9
answer = 1 -> 0 -> 0 -> 0 // 999 + 1 = 1000, the list grows by one node
Example 3
head = 1 -> 9 -> 9
answer = 2 -> 0 -> 0 // the carry travels left until it meets a digit that is not 9
Approach 1: Brute force, reverse, add, reverse back
Intuition. Pen-and-paper addition starts from the units digit and moves left, but a singly linked list can only be walked from the head, which is the most significant digit. The simplest fix is to make the list point the other way: reverse it, so the units digit is the head, perform the schoolbook addition with a carry, and reverse it back. Three linear passes, no extra memory.
Algorithm.
- If the list is empty return a single node
1. - Reverse the list in place.
- Set
carry = 1and walk from the (new) head. At each node computesum = val + carry, storesum % 10and setcarry = sum / 10. Stop as soon as the carry becomes0, since nothing further changes. - If the walk ran off the end with
carrystill1, every digit was a9; append a new node holding1after the last node. Remember the list is still reversed at this point, so appending at the tail is correct. - Reverse the list again and return its head.
static ListNode bruteForce(ListNode head) {
if (head == null) return new ListNode(1); // an empty list stands for 0
head = reverse(head);
int carry = 1; // the +1 we are adding
ListNode cur = head, last = null;
while (cur != null && carry > 0) {
int sum = cur.val + carry;
cur.val = sum % 10;
carry = sum / 10;
last = cur;
cur = cur.next;
}
if (carry > 0) last.next = new ListNode(carry); // every digit was 9: append the new most significant digit (the list is still reversed)
return reverse(head);
}
The reversal helper is the standard three-pointer loop.
static ListNode reverse(ListNode head) {
ListNode prev = null, cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
}
Complexity. Time O(n): two reversals and one addition pass, each linear. Space O(1): a handful of pointers, plus at most one new node.
Why is last guaranteed to be non-null when we append? The loop runs at least once because the list is non-empty and carry starts at 1, so last always points at a real node, and when carry survives the loop it is the final node.
Approach 2: Better, recursion carries the result back up
Intuition. Reversing twice works but feels heavy for what is a single carry propagation. Recursion gives us the right-to-left order for free: a call that descends to the end of the list and does its work after the recursive call returns processes the units digit first, then the tens, and so on, exactly like the written addition. The value a call returns is the carry into the digit to its left.
Algorithm.
addOneRec(node): ifnodeisnull, return1. This is the “+1” entering the units digit.- Otherwise let
carry = addOneRec(node.next), computesum = node.val + carry, storesum % 10in the node and returnsum / 10. - In the wrapper, call
addOneRec(head). If the returned carry is0returnhead; otherwise create a new node holding the carry and make it the new head.
static ListNode better(ListNode head) {
if (head == null) return new ListNode(1);
int carry = addOneRec(head);
if (carry == 0) return head;
return new ListNode(carry, head); // the carry out of the first digit becomes a new leading node
}
static int addOneRec(ListNode node) {
if (node == null) return 1; // base case: the "+1" arrives at the units digit
int carry = addOneRec(node.next);
int sum = node.val + carry;
node.val = sum % 10;
return sum / 10;
}
Complexity. Time O(n): every node is visited once on the way down and once on the way up. Space O(n) for the recursion stack, one frame per digit.
The recursive version is the cleanest to read, but the stack depth equals the number of digits. With 10^5 nodes that is close to the default Java stack limit, which is a real risk in a judge. It also does strictly more work than necessary: once a digit below 9 absorbs the carry, every frame above it still does an addition of 0.
Approach 3: Optimal, one forward pass
Intuition. Look at what adding one actually does to the digits. Scanning from the right, every trailing 9 becomes 0, and the first digit that is not 9 goes up by one. Nothing to the left of that digit changes. So the whole operation is determined by the rightmost digit that is not 9. We can find it in a single left-to-right pass by remembering the most recent non-9 node we have seen: when the pass ends, that remembered node is the rightmost one. Increment it, zero everything after it, done. If no such node exists the number is all 9s, and the answer is a 1 followed by n zeros.
Algorithm.
- If the list is empty return a single node
1. - Walk the list once; whenever
cur.val != 9, setlastNotNine = cur. - If
lastNotNineis stillnull, insert a new node with value0in front of the head and letlastNotNinepoint at it. It plays the role of a leading zero that is about to be incremented. - Increment
lastNotNine.val. - Set every node after
lastNotNineto0. - Return the head (which may be the newly inserted node).
static ListNode optimal(ListNode head) {
if (head == null) return new ListNode(1);
ListNode lastNotNine = null;
for (ListNode cur = head; cur != null; cur = cur.next) {
if (cur.val != 9) lastNotNine = cur;
}
if (lastNotNine == null) { // every digit is 9: 99...9 + 1 = 100...0
lastNotNine = new ListNode(0, head); // a leading 0 that is about to become the new 1
head = lastNotNine;
}
lastNotNine.val++;
for (ListNode cur = lastNotNine.next; cur != null; cur = cur.next) cur.val = 0;
return head;
}
Dry run on head = 2 -> 9 -> 0 -> 9:
| step | cur.val | lastNotNine |
|---|---|---|
| scan | 2 | node(2) |
| scan | 9 | node(2) |
| scan | 0 | node(0) |
| scan | 9 | node(0) |
| increment | node(0) becomes 1 | |
| zero the rest | node(9) after it becomes 0 |
Result: 2 -> 9 -> 1 -> 0, which is 2909 + 1 = 2910. The 9 to the left of the incremented digit was never touched, exactly as in written arithmetic.
Complexity. Time O(n): one scan plus the zeroing pass, which only covers the trailing 9s. Space O(1): one extra pointer and at most one new node. No reversal, no recursion.
Edge cases and pitfalls
- All digits are 9.
9 -> 9 -> 9must become1 -> 0 -> 0 -> 0. Every approach needs a branch that creates one extra node; forgetting it produces0 -> 0 -> 0, which silently drops the carry. - Single digit.
9becomes1 -> 0;0becomes1. The single-node case exercises both the “new head” path and the trivial path. - Empty list. The problem usually guarantees at least one digit; this implementation treats an empty list as
0and returns1. If your judge expectsnullfornull, adjust the first line of each method. - Overflow by conversion. Turning the list into a
long, adding one, and rebuilding fails after 18 or 19 digits. The test file uses a 20-digit input precisely to show that the three list-based methods do not care about length. - Mutating the input. All three methods modify the digits in place. If the caller still needs the original number, clone the list first.
- Recursion depth. Approach 2 uses one stack frame per digit. For very long lists prefer Approach 1 or 3, which are iterative.
- Carry stopping early. In Approach 1 the loop stops as soon as the carry is
0; continuing to the end would still be correct but wastes time on digits that cannot change.
Related problems
- Add two numbers in Linked List is the general form of the same digit-by-digit addition, with two lists and a carry.
- Reverse a LL is the building block used twice in the brute force.
- Reverse a LinkedList, iterative version walks through the three-pointer reversal loop in detail.
- Add two numbers as LinkedList is the SDE sheet version of the two-list addition.