Loading problems...
TL;DR: The optimal solution uses recursion to traverse to the end of the list (the least significant digit), adds one, and propagates any resulting carry backward to the head.
In the LeetCode 369 problem, "Plus One Linked List," we are provided with a singly linked list representing a non-negative integer. The digits are stored in forward order, meaning the head of the list is the most significant digit (e.g., 1 -> 2 -> 3 represents the number 123). Our objective is to add one to this integer and return the modified linked list. We must handle carry-over operations correctly, including edge cases where the number of digits increases (e.g., 9 -> 9 becomes 1 -> 0 -> 0).
A naive approach attempts to convert the linked list structure into a standard integer type, perform the addition, and then reconstruct the list.
1 to this integer.textfunction plusOne(head): num = 0 current = head while current is not null: num = num * 10 + current.val current = current.next num = num + 1 return convertToLinkedList(num)
The fundamental challenge in LeetCode 369 is the direction of the list versus the direction of addition.
To bridge this gap without reversing the list explicitly, we can utilize the call stack via recursion.
The recursion stack allows us to traverse strictly forward to the end of the list. As the recursion unwinds (returns), we effectively move backward from the tail to the head. This allows us to process the addition at the last node and propagate any carry to the previous node, exactly mimicking the manual addition process.
Visual Description: Imagine the recursion tree as a path diving deep into the list.
null terminator after the last node.1 (representing the +1 operation we need to perform).1 up to the next parent. If the sum is less than 10, we update the value and return a carry of 0.
Let's trace the algorithm with the input head = [1, 2, 9].
dfs(1): Calls dfs(2).dfs(2): Calls dfs(9).dfs(9): Calls dfs(null).dfs(null): Returns 1 (the initial +1).carry = 1.sum = 9 + 1 = 10.node.val becomes 10 % 10 = 0.carry = 10 / 10 = 1.carry = 1.sum = 2 + 1 = 3.node.val becomes 3 % 10 = 3.carry = 3 / 10 = 0.carry = 0.sum = 1 + 0 = 1.node.val becomes 1 % 10 = 1.carry = 1 / 10 = 0.dfs(head) returned 0. No new head needed.1 -> 3 -> 0.The algorithm guarantees correctness by enforcing the invariant of standard addition: and .
+1 exactly at the least significant position.cpp/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: // Helper function to perform DFS and return carry int processCarry(ListNode* node) { // Base case: end of list, return 1 to add to the last digit if (!node) { return 1; } // Recursive step: process the rest of the list first int carry = processCarry(node->next); // If there is no carry to add, we can stop early or just return 0 if (carry == 0) return 0; // Perform addition logic int sum = node->val + carry; node->val = sum % 10; return sum / 10; } ListNode* plusOne(ListNode* head) { int carry = processCarry(head); // If there is a remaining carry after processing the head if (carry > 0) { ListNode* newHead = new ListNode(carry); newHead->next = head; return newHead; } return head; } };
java/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode plusOne(ListNode head) { int carry = processCarry(head); // If carry propagates out of the most significant digit if (carry > 0) { ListNode newHead = new ListNode(carry); newHead.next = head; return newHead; } return head; } // Recursive helper to handle addition from LSB to MSB private int processCarry(ListNode node) { if (node == null) { return 1; // Initial +1 at the end of the list } int carry = processCarry(node.next); // Optimization: if carry is 0, no need to update current node if (carry == 0) return 0; int sum = node.val + carry; node.val = sum % 10; return sum / 10; } }
python# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def plusOne(self, head: ListNode) -> ListNode: def process_carry(node): # Base case: if we passed the last node, return 1 (the value to add) if not node: return 1 # Recurse to the end carry = process_carry(node.next) # If no carry coming back, return 0 immediately if carry == 0: return 0 # Update current node total = node.val + carry node.val = total % 10 return total // 10 # Start the recursion from head carry = process_carry(head) # If the head itself generated a carry (e.g., 99 -> 100) if carry: new_head = ListNode(carry) new_head.next = head return new_head return head
The Linked List - Addition of Numbers pattern used in this solution is directly applicable to several other popular interview questions. Mastering the "carry propagation" logic via recursion or stacks is essential for:
Why does my solution get a Time Limit Exceeded (TLE) or Memory Error?
Why is my output 1 -> 0 -> 0 for input 9 -> 9 but 0 -> 0 for others?
head of the list.99 + 100100Why did I get a Null Pointer Exception?
node.next without checking if node is null in the recursive function.null terminator to establish the base case.