Bird
Raised Fist0
DSA Typescriptprogramming

Reverse a Singly Linked List Recursive in DSA Typescript

Choose your learning style10 modes available
Mental Model
We flip the direction of each link by going to the end first, then reversing links on the way back.
Analogy: Imagine unstacking a pile of plates one by one until the last plate, then stacking them back in reverse order.
head -> 1 -> 2 -> 3 -> null
↑
Dry Run Walkthrough
Input: list: 1 -> 2 -> 3 -> null
Goal: Reverse the list so it becomes 3 -> 2 -> 1 -> null
Step 1: call reverse on node 1, recurse to node 2
head -> 1 -> 2 -> 3 -> null
↑ at node 1
Why: We need to reach the last node before reversing links
Step 2: call reverse on node 2, recurse to node 3
head -> 1 -> 2 -> 3 -> null
↑ at node 2
Why: Keep going deeper to the end of the list
Step 3: call reverse on node 3, base case reached (next is null)
head -> 1 -> 2 -> 3 -> null
↑ at node 3
Why: Last node becomes new head of reversed list
Step 4: reverse link: node 3 points to node 2, node 2 next set to null
3 -> 2 -> null
1 -> 2 (detached) -> null
Why: Flip the link between node 2 and 3
Step 5: reverse link: node 2 points to node 1, node 1 next set to null
3 -> 2 -> 1 -> null
Why: Flip the link between node 1 and 2
Step 6: return new head node 3 up the call stack
3 -> 2 -> 1 -> null
Why: Final reversed list head is node 3
Result:
3 -> 2 -> 1 -> null
Annotated Code
DSA Typescript
class ListNode {
  val: number;
  next: ListNode | null;
  constructor(val?: number, next?: ListNode | null) {
    this.val = val === undefined ? 0 : val;
    this.next = next === undefined ? null : next;
  }
}

function reverseListRecursive(head: ListNode | null): ListNode | null {
  if (head === null || head.next === null) {
    return head; // base case: empty or single node list
  }
  const newHead = reverseListRecursive(head.next); // recurse to end
  head.next.next = head; // reverse link: next node points back to current
  head.next = null; // cut original forward link
  return newHead; // return new head up the stack
}

// Driver code to test
const node3 = new ListNode(3);
const node2 = new ListNode(2, node3);
const node1 = new ListNode(1, node2);
const reversedHead = reverseListRecursive(node1);

// Print reversed list
let curr = reversedHead;
let output = "";
while (curr !== null) {
  output += curr.val + " -> ";
  curr = curr.next;
}
output += "null";
console.log(output);
if (head === null || head.next === null) {
base case: stop recursion at empty or last node
const newHead = reverseListRecursive(head.next);
recurse deeper to reach last node
head.next.next = head;
reverse the link by pointing next node back to current
head.next = null;
cut original forward link to avoid cycle
return newHead;
return new head of reversed list up the call stack
OutputSuccess
3 -> 2 -> 1 -> null
Complexity Analysis
Time: O(n) because we visit each node once during recursion
Space: O(n) due to recursion call stack for n nodes
vs Alternative: Iterative reversal uses O(1) space but recursion is simpler to write and understand
Edge Cases
empty list (head is null)
returns null immediately without recursion
DSA Typescript
if (head === null || head.next === null) {
single node list
returns the single node as is, no reversal needed
DSA Typescript
if (head === null || head.next === null) {
When to Use This Pattern
When you see a problem asking to reverse a linked list and recursion is allowed, use the recursive reversal pattern to simplify link flipping by handling the end first.
Common Mistakes
Mistake: Not cutting the original forward link (head.next = null) causing cycles
Fix: Set head.next = null after reversing the link to avoid cycles
Mistake: Returning head instead of newHead causing incorrect list head
Fix: Return newHead which is the last node reached in recursion
Summary
Reverses a singly linked list by recursively flipping links from the end back to the start.
Use when you want a clean, elegant way to reverse a list using recursion.
The key is to reverse links on the way back from the recursion base case, not going down.

Practice

(1/5)
1. What is the main idea behind reversing a singly linked list using recursion?
easy
A. Create a new list and copy nodes in reverse order
B. Swap the values of the first and last nodes only
C. Reverse the rest of the list first, then fix the current node's next pointer
D. Iterate through the list and reverse pointers using a loop

Solution

  1. Step 1: Understand recursion on linked list

    Recursion works by solving a smaller part first, here reversing the rest of the list beyond the current node.
  2. Step 2: Fix current node's pointer after recursion

    After the rest is reversed, the current node's next node points back to it, reversing the link.
  3. Final Answer:

    Reverse the rest of the list first, then fix the current node's next pointer -> Option C
  4. Quick Check:

    Recursive reversal = reverse rest + fix pointer [OK]
Hint: Think: reverse smaller list first, then fix current link [OK]
Common Mistakes:
  • Trying to swap node values instead of pointers
  • Not fixing the current node's next pointer after recursion
  • Using iteration instead of recursion
2. Which of the following is the correct base case for a recursive function that reverses a singly linked list?
easy
A. if (head === null) return head.next;
B. if (head.next === null) return null;
C. if (head === null) return head.next.next;
D. if (head === null || head.next === null) return head;

Solution

  1. Step 1: Identify when recursion should stop

    The base case is when the list is empty or has only one node, so no reversal needed.
  2. Step 2: Check the correct base case syntax

    Return the head if it is null or its next is null, meaning end or single node.
  3. Final Answer:

    if (head === null || head.next === null) return head; -> Option D
  4. Quick Check:

    Base case = empty or single node [OK]
Hint: Base case: empty or single node returns itself [OK]
Common Mistakes:
  • Returning null when only one node exists
  • Accessing head.next without checking if head is null
  • Incorrectly returning head.next or head.next.next
3. What will be the output linked list after running this recursive reverse function on the list 1 -> 2 -> 3 -> null?
function reverseList(head: ListNode | null): ListNode | null {
  if (!head || !head.next) return head;
  const newHead = reverseList(head.next);
  head.next.next = head;
  head.next = null;
  return newHead;
}
medium
A. 3 -> 2 -> 1 -> null
B. 1 -> 2 -> 3 -> null
C. null
D. 2 -> 3 -> 1 -> null

Solution

  1. Step 1: Trace recursion on list 1 -> 2 -> 3

    Recursion goes to node 3 (base case), then reverses links back: 3 points to 2, 2 points to 1.
  2. Step 2: Update pointers to reverse list

    head.next.next = head sets 2's next to 1, head.next = null breaks old link, final reversed list is 3 -> 2 -> 1 -> null.
  3. Final Answer:

    3 -> 2 -> 1 -> null -> Option A
  4. Quick Check:

    Reversed list = 3 -> 2 -> 1 [OK]
Hint: Last node becomes new head after recursion [OK]
Common Mistakes:
  • Not setting head.next to null causing cycles
  • Returning original head instead of new head
  • Confusing node values with pointers
4. Identify the bug in this recursive reverse function and choose the fix:
function reverseList(head: ListNode | null): ListNode | null {
  if (!head) return null;
  if (!head.next) return head;
  const newHead = reverseList(head.next);
  head.next = null;
  head.next.next = head;
  return newHead;
}
medium
A. Remove the base case for head.next === null
B. Swap the last two pointer assignments: set head.next.next before head.next = null
C. Return head instead of newHead
D. Add a loop to reverse pointers instead of recursion

Solution

  1. Step 1: Analyze pointer assignments order

    Setting head.next = null before head.next.next = head breaks the chain because head.next becomes null.
  2. Step 2: Correct order to fix pointers

    First set head.next.next = head to reverse link, then set head.next = null to break old link.
  3. Final Answer:

    Swap the last two pointer assignments: set head.next.next before head.next = null -> Option B
  4. Quick Check:

    Fix pointer order to avoid null errors [OK]
Hint: Set head.next.next before nullifying head.next [OK]
Common Mistakes:
  • Nullifying head.next too early
  • Ignoring base cases
  • Returning wrong node
5. Given a singly linked list with nodes containing values [10, 20, 30, 40, 50], which recursive approach correctly reverses the list and returns the new head?
function reverseList(head: ListNode | null): ListNode | null {
  if (!head || !head.next) return head;
  const newHead = reverseList(head.next);
  head.next.next = head;
  head.next = null;
  return newHead;
}
What will be the final linked list after calling reverseList on the head node with value 10?
hard
A. 50 -> 40 -> 30 -> 20 -> 10 -> null
B. 10 -> 20 -> 30 -> 40 -> 50 -> null
C. null
D. 20 -> 30 -> 40 -> 50 -> 10 -> null

Solution

  1. Step 1: Understand recursive reversal on list [10,20,30,40,50]

    The recursion reaches the last node (50), then reverses links step-by-step back to the first node.
  2. Step 2: Trace pointer changes during recursion unwind

    Each node's next node points back to it, and its next pointer is set to null, resulting in reversed list 50 -> 40 -> 30 -> 20 -> 10 -> null.
  3. Final Answer:

    50 -> 40 -> 30 -> 20 -> 10 -> null -> Option A
  4. Quick Check:

    Recursive reverse flips list order [OK]
Hint: Last node becomes new head, links reversed back [OK]
Common Mistakes:
  • Expecting original order after reversal
  • Not setting head.next to null causing cycles
  • Confusing node values with pointers
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard