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:

Python
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 head

The 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:

TypeScript
start prev=None curr=1 123 → None
after pass 1 prev=1 curr=2 1 → None, 23 → None
after pass 2 prev=2 curr=3 21 → None
after pass 3 prev=3 curr=None 321 → None

The 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:

Python
class Node:
def __init__(self, action, nxt=None):
self.action, self.next = action, nxt
history = Node('delete', Node('paste', Node('type'))) # newest first
oldest_first = reverse(history)
node = oldest_first
while node:
replay(node.action) # type, paste, delete
node = node.next

Reversing 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?

More Linked Lists interview questions

View all →