Reverse Linked List
Reverse a singly linked list in place — iterative three-pointer walk, recursive version, and the interview follow-ups.
- dsa
- linked-list
- interview
- Meta
- Amazon
- Microsoft
- Uber
The problem
Given the head of a singly linked list, reverse the list and return the new head.
Input: 1 → 2 → 3 → 4 → 5 → null
Output: 5 → 4 → 3 → 2 → 1 → null
Input: null
Output: null
Input: 1 → null
Output: 1 → null
Constraints you should restate: nodes are typical { val, next }; list may be empty; do it in O(1) extra space if asked for in-place.
Why it shows up: pointer rewiring under pressure. Frontend cousins — undo stacks of list nodes, reverse of a playlist queue, interview warm-ups before harder list problems (cycle, reorder, reverse k-group).
Node shape
class ListNode {
val: number;
next: ListNode | null;
constructor(val = 0, next: ListNode | null = null) {
this.val = val;
this.next = next;
}
}
Brute force (mention, then skip)
Walk the list into an array, reverse the array, rebuild nodes. Correct, O(n) space, looks like you panicked. Say it in one sentence and move on.
Optimal: iterative three pointers
Keep prev, curr, and next (or save curr.next before you overwrite it).
prev = null,curr = head- While
curr:- save
next = curr.next curr.next = prev- advance
prev = curr,curr = next
- save
- Return
prev(new head)
function reverseList(head: ListNode | null): ListNode | null {
let prev: ListNode | null = null;
let curr = head;
while (curr) {
const next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
| Time | O(n) |
| Space | O(1) |
Walk 1 → 2 → 3
| step | prev | curr | list shape |
|---|---|---|---|
| start | null | 1 | 1→2→3 |
| after 1 | 1 | 2 | 1→null, 2→3 |
| after 2 | 2 | 3 | 2→1→null, 3→null pending |
| after 3 | 3 | null | 3→2→1→null |
Recursive version (know it)
Reverse the rest, then make the next node point back at you, and cut your forward link.
function reverseListRecursive(head: ListNode | null): ListNode | null {
if (!head || !head.next) return head;
const newHead = reverseListRecursive(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
| Time | O(n) |
| Space | O(n) call stack |
Prefer iterative in interviews unless they ask for recursion or stack-depth discussion.
Edge cases to say out loud
- Empty list → return
null - Single node → return same node
- Two nodes — classic off-by-one zone; dry-run once
- Do not lose the rest of the list: always save
nextbefore rewiring - Cycle? Classic problem assumes acyclic; if input may cycle, detect first
Common bugs
- Forgetting to save
next→ infinite loop or lost tail - Returning
headinstead ofprev - Leaving the old head’s
nextpointing into the old chain (recursive: forgethead.next = null) - Mutating values instead of pointers (works for numbers only; wrong skill)
Follow-ups
- Reverse Linked List II — reverse between left and right indices
- Reverse Nodes in k-Group — hard; group-wise reverse
- Palindrome Linked List — reverse second half, compare
- Reorder List — split, reverse second half, merge
Interview delivery
- Clarify singly vs doubly, empty list, in-place.
- Draw three nodes; name
prev/curr/next. - Code iterative cleanly.
- Trace one example.
- State O(n) time, O(1) space.
- Offer recursive if they want.
Related
- Linked List Cycle
- Merge Two Sorted Lists
- Remove Nth Node From End
- Reorder List
- LRU Cache — pointers + map