Recursion-Based Structures (Linked List Ops, Nested Structures)
📖 Concept
Many data structure operations are naturally recursive. Understanding how to think recursively about linked lists, nested arrays, and tree-like structures is essential for interviews.
Why recursion fits certain structures:
- Linked lists are recursive by definition: a node + a smaller linked list
- Nested arrays/objects have unknown depth — recursion handles any depth
- Trees are recursive: a node + left subtree + right subtree
The recursive linked list mental model:
[1] → [2] → [3] → null
↓
1 + recurse([2] → [3] → null)
↓
2 + recurse([3] → null)
↓
3 + recurse(null) → base case: 0
Key patterns:
- Process current node + recurse on rest (linked list sum, length, contains)
- Recurse first, then process (reverse linked list, reverse nested)
- Recurse on all children (flatten nested arrays, deep clone objects)
- Divide into halves (merge sort on linked list)
🏠 Real-world analogy: Recursion on a linked list is like a relay race — each runner (node) does their part and passes the baton (result) to the next runner. The last runner (base case) sends the result back.
💻 Code Example
1// RECURSIVE LINKED LIST OPERATIONS23class ListNode {4 constructor(val, next = null) {5 this.val = val;6 this.next = next;7 }8}910// Sum all values — recursively11function sumList(head) {12 if (!head) return 0; // Base case13 return head.val + sumList(head.next); // Current + rest14}1516// Reverse linked list — recursively17function reverseListRecursive(head) {18 if (!head || !head.next) return head; // Base case19 const newHead = reverseListRecursive(head.next); // Recurse to end20 head.next.next = head; // Reverse pointer21 head.next = null; // Clean old pointer22 return newHead;23}2425// Check if linked list contains value26function contains(head, target) {27 if (!head) return false;28 if (head.val === target) return true;29 return contains(head.next, target);30}3132// DEEP FLATTEN NESTED ARRAYS33function deepFlatten(arr) {34 const result = [];35 for (const item of arr) {36 if (Array.isArray(item)) {37 result.push(...deepFlatten(item)); // Recurse into nested38 } else {39 result.push(item);40 }41 }42 return result;43}44// [1, [2, [3, [4]], 5]] → [1, 2, 3, 4, 5]4546// DEEP CLONE OBJECTS — handles nested objects/arrays47function deepClone(obj) {48 if (obj === null || typeof obj !== 'object') return obj;49 if (Array.isArray(obj)) return obj.map(item => deepClone(item));50 const clone = {};51 for (const key of Object.keys(obj)) {52 clone[key] = deepClone(obj[key]);53 }54 return clone;55}5657// TypeScript — Deep nested sum58interface NestedInteger {59 value?: number;60 list?: NestedInteger[];61}6263function nestedSum(nested: NestedInteger[]): number {64 let total = 0;65 for (const item of nested) {66 if (item.value !== undefined) {67 total += item.value;68 } else if (item.list) {69 total += nestedSum(item.list);70 }71 }72 return total;73}7475// MERGE SORT ON LINKED LIST — Divide & Conquer76function mergeSortList(head) {77 if (!head || !head.next) return head;78 const mid = getMiddle(head);79 const right = mid.next;80 mid.next = null; // Split81 return mergeTwoLists(mergeSortList(head), mergeSortList(right));82}8384function getMiddle(head) {85 let slow = head, fast = head.next;86 while (fast && fast.next) {87 slow = slow.next;88 fast = fast.next.next;89 }90 return slow;91}9293function mergeTwoLists(l1, l2) {94 const dummy = new ListNode(0);95 let curr = dummy;96 while (l1 && l2) {97 if (l1.val <= l2.val) { curr.next = l1; l1 = l1.next; }98 else { curr.next = l2; l2 = l2.next; }99 curr = curr.next;100 }101 curr.next = l1 || l2;102 return dummy.next;103}
🏋️ Practice Exercise
Practice Problems:
- Find the length of a linked list recursively
- Print a linked list in reverse order (without reversing it) using recursion
- Deep flatten a nested array of any depth
- Deep clone a nested object (handle arrays, objects, primitives)
- Recursively sum all numbers in a nested structure like NestedInteger
- Sort a linked list using merge sort (recursive divide & conquer)
- Remove all occurrences of a value from a linked list recursively
- Check if two nested structures are deeply equal
- Recursively find the maximum depth of a nested array
- Convert a nested list to a flat list preserving order
⚠️ Common Mistakes
Not identifying the base case for recursive linked list operations — it's usually !head or !head.next
Forgetting to return the new head after recursive reversal — the recursion returns the new head all the way up
Stack overflow on deeply nested structures — convert to iterative with explicit stack for very deep nesting
Modifying the original data structure when a deep clone is needed — always create new nodes/objects
Not handling circular references in deep clone — add a visited set for production code
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Recursion-Based Structures (Linked List Ops, Nested Structures)