🧠
Recursive Length Alignment and Addition Without Extra Space
💡 This approach aligns the two lists by length and recursively adds corresponding nodes, handling carry on the way back. It avoids extra data structures but is more complex.
Intuition
Pad the shorter list with zeros, recursively add nodes from most significant to least significant, propagate carry back up the recursion stack.
Algorithm
- Calculate lengths of both lists.
- Pad the shorter list with zeros at the front to match lengths.
- Recursively add corresponding nodes starting from the head.
- Propagate carry back up and create new head if needed.
💡 This approach is harder because you must manage padding and carry propagation recursively, but it uses no extra stacks or reversal.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def getLength(head):
length = 0
while head:
length += 1
head = head.next
return length
def padList(head, padding):
for _ in range(padding):
head = ListNode(0, head)
return head
def addListsHelper(l1, l2):
if not l1 and not l2:
return (None, 0)
next_node, carry = addListsHelper(l1.next, l2.next)
total = l1.val + l2.val + carry
node = ListNode(total % 10)
node.next = next_node
return (node, total // 10)
def addTwoNumbers(l1, l2):
len1 = getLength(l1)
len2 = getLength(l2)
if len1 < len2:
l1 = padList(l1, len2 - len1)
else:
l2 = padList(l2, len1 - len2)
head, carry = addListsHelper(l1, l2)
if carry:
head = ListNode(carry, head)
return head
# Driver code
if __name__ == '__main__':
def create_list(arr):
head = None
for val in reversed(arr):
head = ListNode(val, head)
return head
def print_list(node):
vals = []
while node:
vals.append(str(node.val))
node = node.next
print('[' + ','.join(vals) + ']')
l1 = create_list([7,2,4,3])
l2 = create_list([5,6,4])
res = addTwoNumbers(l1, l2)
print_list(res)
Line Notes
def getLength(head):Helper to find length of linked list for padding
def padList(head, padding):Add zeros in front to equalize lengths
def addListsHelper(l1, l2):Recursive helper to add nodes and carry
next_node, carry = addListsHelper(l1.next, l2.next)Recursive call to process next digits first
node = ListNode(total % 10)Create node for current digit after addition
if carry:If carry remains after full addition, add new head node
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
}
public class Solution {
private int getLength(ListNode head) {
int length = 0;
while (head != null) {
length++;
head = head.next;
}
return length;
}
private ListNode padList(ListNode head, int padding) {
for (int i = 0; i < padding; i++) {
ListNode node = new ListNode(0);
node.next = head;
head = node;
}
return head;
}
private class SumResult {
ListNode node;
int carry;
SumResult(ListNode node, int carry) {
this.node = node;
this.carry = carry;
}
}
private SumResult addListsHelper(ListNode l1, ListNode l2) {
if (l1 == null && l2 == null) return new SumResult(null, 0);
SumResult next = addListsHelper(l1.next, l2.next);
int sum = l1.val + l2.val + next.carry;
ListNode node = new ListNode(sum % 10);
node.next = next.node;
return new SumResult(node, sum / 10);
}
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int len1 = getLength(l1);
int len2 = getLength(l2);
if (len1 < len2) l1 = padList(l1, len2 - len1);
else l2 = padList(l2, len1 - len2);
SumResult res = addListsHelper(l1, l2);
if (res.carry != 0) {
ListNode node = new ListNode(res.carry);
node.next = res.node;
return node;
}
return res.node;
}
public static void main(String[] args) {
Solution sol = new Solution();
ListNode l1 = new ListNode(7);
l1.next = new ListNode(2);
l1.next.next = new ListNode(4);
l1.next.next.next = new ListNode(3);
ListNode l2 = new ListNode(5);
l2.next = new ListNode(6);
l2.next.next = new ListNode(4);
ListNode res = sol.addTwoNumbers(l1, l2);
while (res != null) {
System.out.print(res.val);
if (res.next != null) System.out.print(",");
res = res.next;
}
System.out.println();
}
}
Line Notes
private int getLength(ListNode head)Calculate length to pad shorter list
private ListNode padList(ListNode head, int padding)Add zeros at front to equalize lengths
private SumResult addListsHelper(ListNode l1, ListNode l2)Recursive addition returning node and carry
SumResult next = addListsHelper(l1.next, l2.next);Process next digits first to handle carry
ListNode node = new ListNode(sum % 10);Create node for current digit
if (res.carry != 0)Add new head if carry remains after recursion
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
int getLength(ListNode* head) {
int length = 0;
while (head) {
length++;
head = head->next;
}
return length;
}
ListNode* padList(ListNode* head, int padding) {
for (int i = 0; i < padding; i++) {
ListNode* node = new ListNode(0);
node->next = head;
head = node;
}
return head;
}
struct SumResult {
ListNode* node;
int carry;
SumResult(ListNode* n, int c) : node(n), carry(c) {}
};
SumResult addListsHelper(ListNode* l1, ListNode* l2) {
if (!l1 && !l2) return SumResult(nullptr, 0);
SumResult next = addListsHelper(l1->next, l2->next);
int sum = l1->val + l2->val + next.carry;
ListNode* node = new ListNode(sum % 10);
node->next = next.node;
return SumResult(node, sum / 10);
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int len1 = getLength(l1);
int len2 = getLength(l2);
if (len1 < len2) l1 = padList(l1, len2 - len1);
else l2 = padList(l2, len1 - len2);
SumResult res = addListsHelper(l1, l2);
if (res.carry != 0) {
ListNode* node = new ListNode(res.carry);
node->next = res.node;
return node;
}
return res.node;
}
};
int main() {
Solution sol;
ListNode* l1 = new ListNode(7);
l1->next = new ListNode(2);
l1->next->next = new ListNode(4);
l1->next->next->next = new ListNode(3);
ListNode* l2 = new ListNode(5);
l2->next = new ListNode(6);
l2->next->next = new ListNode(4);
ListNode* res = sol.addTwoNumbers(l1, l2);
while (res) {
cout << res->val;
if (res->next) cout << ",";
res = res->next;
}
cout << endl;
return 0;
}
Line Notes
int getLength(ListNode* head)Calculate length to pad shorter list
ListNode* padList(ListNode* head, int padding)Add zeros at front to equalize lengths
SumResult addListsHelper(ListNode* l1, ListNode* l2)Recursive addition returning node and carry
SumResult next = addListsHelper(l1->next, l2->next);Process next digits first to handle carry
ListNode* node = new ListNode(sum % 10);Create node for current digit
if (res.carry != 0)Add new head if carry remains after recursion
function ListNode(val, next = null) {
this.val = val;
this.next = next;
}
function getLength(head) {
let length = 0;
while (head) {
length++;
head = head.next;
}
return length;
}
function padList(head, padding) {
for (let i = 0; i < padding; i++) {
head = new ListNode(0, head);
}
return head;
}
function addListsHelper(l1, l2) {
if (!l1 && !l2) return { node: null, carry: 0 };
const next = addListsHelper(l1.next, l2.next);
const sum = l1.val + l2.val + next.carry;
const node = new ListNode(sum % 10);
node.next = next.node;
return { node: node, carry: Math.floor(sum / 10) };
}
function addTwoNumbers(l1, l2) {
const len1 = getLength(l1);
const len2 = getLength(l2);
if (len1 < len2) l1 = padList(l1, len2 - len1);
else l2 = padList(l2, len1 - len2);
const res = addListsHelper(l1, l2);
if (res.carry) {
return new ListNode(res.carry, res.node);
}
return res.node;
}
// Test code
function createList(arr) {
let head = null;
for (let i = arr.length - 1; i >= 0; i--) {
head = new ListNode(arr[i], head);
}
return head;
}
function printList(node) {
const vals = [];
while (node) {
vals.push(node.val);
node = node.next;
}
console.log('[' + vals.join(',') + ']');
}
const l1 = createList([7,2,4,3]);
const l2 = createList([5,6,4]);
const res = addTwoNumbers(l1, l2);
printList(res);
Line Notes
function getLength(head)Calculate length to pad shorter list
function padList(head, padding)Add zeros at front to equalize lengths
function addListsHelper(l1, l2)Recursive addition returning node and carry
const next = addListsHelper(l1.next, l2.next);Process next digits first to handle carry
const node = new ListNode(sum % 10);Create node for current digit
if (res.carry)Add new head if carry remains after recursion
TimeO(n + m)
SpaceO(n + m) due to recursion stack
Padding and length calculation are O(n + m), recursion depth is O(n), building result is O(n).
💡 For input size 100,000, recursion depth is large but acceptable in many environments; no extra data structures used.
Interview Verdict: Accepted
This approach is elegant and uses no extra data structures but requires careful recursion and padding logic.