Reverse Linked List: The Pointer Swap Technique
Reverse Linked List is LeetCode problem 206. It is one of the most classic interview questions, and for good reason. It tests whether you truly understand how pointers work. Not in theory. In practice, under pressure, with a whiteboard marker in your hand.
The problem is rated Easy, but it trips people up constantly. If you cannot reverse a linked list from memory in under two minutes, you will struggle with every linked list problem that builds on top of it.
The problem
You are given the head of a singly linked list. Reverse the list and return the new head.
Example: 1 -> 2 -> 3 -> 4 -> 5 -> null becomes 5 -> 4 -> 3 -> 2 -> 1 -> null.
Why this is tricky
With arrays, reversing is simple: swap the first and last elements, then move inward. You have random access to any index.
Linked lists do not give you that luxury. Each node only knows about the next node. There is no "previous" pointer. There is no way to jump to the end. You are stuck walking forward, one node at a time.
So when you point node 2's next to node 1 (reversing that arrow), you lose your reference to node 3. The chain breaks. You are stranded.
The fix: save a reference to the next node before you break the link. That is the entire trick.
The three-pointer technique
You need three pointers:
- prev - the node behind curr (starts as
null) - curr - the node you are currently processing (starts at
head) - next_node - a temporary save of
curr.nextbefore you overwrite it
At each step:
- Save
curr.nextintonext_node(so you do not lose it) - Point
curr.nexttoprev(reverse the arrow) - Move
prevforward tocurr - Move
currforward tonext_node
When curr becomes null, you have processed every node. prev now points to the last node you visited, which is the new head of the reversed list. Return prev.
Visual walkthrough
Let's trace through reversing 1 -> 2 -> 3 -> 4 -> null. Watch prev (purple) and curr (amber) as they march through the list, flipping each arrow as they go.
Initial state: prev = null, curr = 1
prev is null (not shown). curr starts at the head.
Step 1: Save next = 2. Point 1.next = null. Move prev and curr right.
Node 1 now points to null. We move prev to 1, curr to 2.
Step 2: Save next = 3. Point 2.next = 1. Move prev and curr right.
Node 2 now points back to 1. prev moves to 2, curr moves to 3.
Step 3: Save next = 4. Point 3.next = 2. Move prev and curr right.
Node 3 now points back to 2. prev moves to 3, curr moves to 4.
Step 4: Save next = null. Point 4.next = 3. curr becomes null. Done!
All arrows reversed. prev points to 4, which is our new head. Return prev.
Notice the pattern: at each step, exactly one arrow gets reversed. By the end, every arrow points backwards and prev is sitting on the new head. Clean and predictable.
The iterative solution
def reverseList(head):
prev = None
curr = head
while curr:
next_node = curr.next # save
curr.next = prev # reverse
prev = curr # advance prev
curr = next_node # advance curr
return prev
Four lines inside the loop, each doing exactly one thing. This is one of those solutions where every line is load-bearing. Remove any one of them and it breaks.
A common bug is forgetting to save curr.next before overwriting it. If you write curr.next = prev first, you have lost your only way forward. Always save before you swap.
The recursive solution
The recursive approach is more elegant but harder to reason about. The idea: assume the rest of the list is already reversed. Then fix the connection between the current node and the next node.
def reverseList(head):
if not head or not head.next:
return head
new_head = reverseList(head.next)
head.next.next = head
head.next = None
return new_head
Here is what is happening:
- Base case: If the list is empty or has one node, it is already reversed. Return it.
- Recurse: Reverse everything after
head. The returnednew_headis the tail of the original list, which is now the head of the reversed list. - Fix the link:
head.nextis the node right afterhead. That node'snextshould now point back tohead. Sohead.next.next = head. - Break the old link: Set
head.next = Noneso the original forward arrow is removed. - Pass up the new head:
new_headbubbles all the way back up the call stack unchanged.
The recursive version is elegant, but it uses O(n) stack space. For very long lists, that can be a problem. The iterative version is O(1) space and generally preferred in interviews.
Complexity analysis
Time: O(n) for both approaches. You visit each node exactly once. There is no way to do better since you need to touch every arrow.
Space: O(1) for the iterative approach. You only use three pointer variables regardless of list length. The recursive approach is O(n) space due to the call stack.
Edge cases to watch for
- Empty list (head is null). The while loop never runs.
prevstaysNone. ReturnNone. Correct. - Single node. The while loop runs once, sets
curr.next = None(it was already null), and moves on. Returns the single node. Correct. - Two nodes. The simplest case where an actual reversal happens. Good for verifying your logic by hand.
- Very long list. The iterative solution handles this fine. The recursive solution might hit a stack overflow in languages without tail-call optimization (which includes Python).
The Building Blocks
This problem is built from one core building block:
In-place pointer reversal. You have a chain of references, and you need to flip them one by one without losing your place. The technique: always save the next reference before you overwrite it, then advance your "previous" and "current" pointers in lockstep.
This brick shows up everywhere in linked list problems:
- Reverse Linked List II (LeetCode 92) reverses only a subsection of the list. Same pointer swap, but you need to reconnect the boundaries.
- Palindrome Linked List (LeetCode 234) reverses the second half, then compares it to the first half.
- Reorder List (LeetCode 143) splits the list in half, reverses the back half, then interleaves the two halves.
- Reverse Nodes in k-Group (LeetCode 25) applies the reversal in chunks of k nodes. Hard problem, but the inner loop is exactly this technique.
- Swap Nodes in Pairs (LeetCode 24) is a special case of k-group reversal with k = 2.
Once you can reverse a linked list without thinking, you unlock an entire family of problems. This is not a standalone trick. It is a fundamental building block.
The "save before you swap" principle appears in many contexts beyond linked lists. Whenever you need to rearrange pointers or references in-place, the pattern is the same: save what you are about to overwrite, make the change, then advance using what you saved.
Why you will forget this (and how to fix it)
This is a six-line solution. You will read it, understand it, and feel confident. Then in an interview two weeks from now, you will mix up the order of the pointer assignments and spend five minutes debugging.
The problem is not understanding. It is recall under pressure. You need to have typed this solution from scratch enough times that your fingers know the order: save, reverse, advance prev, advance curr. No hesitation.
Spaced repetition makes this automatic. You type it today, again in two days, again in a week. After a few reps, the pointer dance is muscle memory. You do not think about which variable to update first. You just do it.
Related posts
- Merge Sorted Array - Another problem where pointer manipulation order matters and getting it wrong means losing data
- Valid Parentheses - A different data structure (stacks), but the same idea of tracking state as you walk through a sequence