Reverse a Singly Linked List Recursive in DSA Javascript - Time & Space Complexity
We want to understand how long it takes to reverse a singly linked list using recursion.
The question is: how does the time grow as the list gets longer?
Analyze the time complexity of the following code snippet.
function reverseList(head) {
if (!head || !head.next) return head;
const newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
This code reverses a singly linked list by calling itself on the next node until it reaches the end, then rewires the pointers backward.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive call on each node of the list.
- How many times: Once per node, so as many times as the list length (n).
Each node causes one recursive call, so the number of operations grows directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 recursive calls and rewiring steps |
| 100 | About 100 recursive calls and rewiring steps |
| 1000 | About 1000 recursive calls and rewiring steps |
Pattern observation: The work grows linearly as the list gets longer.
Time Complexity: O(n)
This means the time to reverse the list grows in direct proportion to the number of nodes.
[X] Wrong: "Recursion makes this slower than a loop, so it must be more than linear time."
[OK] Correct: Each node is still visited once, so recursion here does not add extra repeated work beyond linear time.
Understanding recursive time complexity helps you explain your code clearly and shows you can reason about performance, a key skill in interviews.
"What if we changed the recursion to an iterative loop? How would the time complexity change?"
Practice
Solution
Step 1: Understand recursion on linked list
Recursion reverses the list by first reversing the smaller list after the current node.Step 2: Fix the current node's next pointer
After recursion returns, the current node's next node points back to the current node, reversing the link.Final Answer:
Reverse the rest of the list first, then fix the current node's next pointer -> Option BQuick Check:
Recursive reversal = Reverse rest then fix current [OK]
- Trying to swap node values instead of pointers
- Using iteration instead of recursion
- Not fixing the current node's next pointer after recursion
Solution
Step 1: Identify base cases for recursion
The base case must handle empty list (null) and single node list (next is null).Step 2: Combine conditions for base case
Return head if it is null or if it is the last node (head.next is null).Final Answer:
if (head === null || head.next === null) return head; -> Option DQuick Check:
Base case = empty or single node list [OK]
- Using only null check without single node check
- Returning wrong node in base case
- Checking head.next.next which may cause error if head.next is null
function reverseList(head) {
if (head === null || head.next === null) return head;
const newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}Solution
Step 1: Trace recursion on list 1 -> 2 -> 3
Recursion reaches last node 3, returns it as new head.Step 2: Reverse pointers on unwind
Node 2's next (3) points back to 2, then 2's next set to null; similarly for node 1.Final Answer:
3 -> 2 -> 1 -> null -> Option CQuick Check:
Recursive reversal output = reversed list [OK]
- Not setting head.next to null causing cycles
- Returning original head instead of new head
- Confusing node values with pointers
function reverseList(head) {
if (!head || !head.next) return head;
const newHead = reverseList(head.next);
head.next = head;
head.next = null;
return newHead;
}Solution
Step 1: Analyze pointer assignment
head.next = head sets next pointer of current node to itself, causing cycle.Step 2: Correct pointer fix
It should be head.next.next = head to reverse the link properly.Final Answer:
head.next = head; creates a cycle, should be head.next.next = head; -> Option AQuick Check:
Pointer fix must be head.next.next = head [OK]
- Assigning head.next to head causing infinite loop
- Forgetting to set head.next to null
- Incorrect base case handling
Solution
Step 1: Change recursion to return both head and count
Return an object with newHead and count from each recursive call.Step 2: Increment count on each unwind step
When recursion returns, add 1 to count to track nodes reversed.Final Answer:
Return an object {newHead, count} from recursion and increment count on unwind -> Option AQuick Check:
Return combined result object with count [OK]
- Using global variables causing side effects
- Counting nodes before reversal, not during recursion
- Modifying node structure unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
