How do you reverse a singly linked list?
Updated Feb 20, 2026
Short answer
Walk the list once, re-pointing each node's next at the node behind it. You need three references — previous, current, and a saved copy of the next node, because overwriting current.next would otherwise lose the rest of the list. It runs in O(n) time and O(1) space, and the loop ends with prev holding the new head.
Deep explanation
The iterative version is the one to know cold:
def reverse(head): prev = None curr = head while curr: nxt = curr.next # SAVE the rest of the list first curr.next = prev # re-point backwards prev = curr # advance both pointers curr = nxt return prev # curr is now None; prev is the new headThe order of those four lines is the whole problem. Assigning curr.next = prev before saving curr.next orphans everything downstream — the single most common way this is written wrong.
Tracing 1 → 2 → 3:
start prev=None curr=1 1 → 2 → 3 → Noneafter pass 1 prev=1 curr=2 1 → None, 2 → 3 → Noneafter pass 2 prev=2 curr=3 2 → 1 → Noneafter pass 3 prev=3 curr=None 3 → 2 → 1 → NoneThe loop exits when curr is None, at which point prev points at the last node visited — the new head.
A recursive version exists and reads elegantly, but it costs O(n) stack space and overflows on a long list, so the iterative form is preferred in production. Both are O(n) time; only the space differs.
Edge cases fall out naturally: an empty list returns None, and a single node returns itself, since the loop body runs once and simply points it at None.
Real-world example
An undo history stored newest-first needs to be replayed oldest-first:
class Node: def __init__(self, action, nxt=None): self.action, self.next = action, nxt
history = Node('delete', Node('paste', Node('type'))) # newest firstoldest_first = reverse(history)
node = oldest_firstwhile node: replay(node.action) # type, paste, delete node = node.nextReversing in place costs nothing extra in memory, which matters when the history is long — copying into a list and reversing that would double the footprint.
Common mistakes
- - Overwriting `curr.next` before saving it, which severs the remainder of the list.
- - Returning `head` instead of `prev`
- the original head is the tail after reversal and now points at None.
- - Forgetting to set the original head's `next` to None — handled automatically here because `prev` starts as None.
- - Using the recursive version on a long list and overflowing the call stack.
- - Failing the empty-list case by dereferencing `head.next` before checking `head` is not None.
Follow-up questions
- How would you reverse only a sublist between positions m and n?
- What is the space complexity of the recursive version?
- How does reversing a doubly linked list differ?
- How would you check whether a linked list is a palindrome?