Reverse a Linked List
Table of Contents + β
This one looks small. But it trips up so many people in interviews. When the interviewer asks you to reverse a linked list, they are not testing if you know what a linked list is. They want to see if you can move pointers around without losing the rest of the list. So the real test here is careful pointer handling. Lose one link, and the whole chain after it is lost.
π The Problem
You are given the head of a singly linked list. A singly linked list is a chain of nodes. Each node holds a value and a pointer to the next node. Your job is to reverse it. So the last node becomes the first, and the first becomes the last.
Input: 1 -> 2 -> 3 -> NULLOutput: 3 -> 2 -> 1 -> NULLSee, the values stay the same. Only the direction of the arrows flips.
π’ The Simple Idea First
The easy way is to walk the list, copy every value into an array, then build a brand new list from the back. That works. But think about it. You just used extra space equal to the whole list. And you created a second list when you did not need to.
The interviewer will almost always ask: can you do it in place? In place means you reverse the same list without making a new one. So we should aim for no extra memory. That is where the three-pointer approach comes in.
π€ How the Three Pointers Move
Here is the whole trick. We keep three pointers as we walk:
prevβ the node behind us. It starts asNULL.currβ the node we are looking at right now.nextβ a safety pointer that remembers what comes aftercurr.
Why do we need next? Because the moment we flip currβs arrow to point backward, we lose the path forward. So we save it first.
Let me show one step. Say we are here:
NULL 1 -> 2 -> 3 -> NULL ^ ^prev currFirst we save next so we do not lose node 2:
next = 2Then we flip currβs arrow to point back at prev:
NULL <- 1 2 -> 3 -> NULLNow we slide both pointers one step forward. prev becomes curr, and curr becomes next:
NULL <- 1 2 -> 3 -> NULL ^ ^ prev currWe repeat this until curr reaches the end and becomes NULL. At that point prev is sitting on the last node we touched, which is now the new head. So we return prev.
πͺ Steps to Reverse the List
- Set
prev = NULLandcurr = head. - While
curris notNULL, do the next steps. - Save
next = curr.nextso the rest of the list is safe. - Point
curr.nextback toprev. - Move
prev = currandcurr = next. - When the loop ends,
previs the new head. Return it.
Now here is the code that builds a list, reverses it, and prints both.
# One node of the listclass Node: def __init__(self, data): self.data = data self.next = None
# Reverse the list and return the new headdef reverse(head): prev = None curr = head while curr is not None: nxt = curr.next # save the rest curr.next = prev # flip the arrow back prev = curr # slide prev forward curr = nxt # slide curr forward return prev # prev is the new head
# Print the list as "1 -> 2 -> 3 -> NULL"def print_list(head): parts = [] while head is not None: parts.append(str(head.data)) head = head.next print(" -> ".join(parts) + " -> NULL")
# Build 1 -> 2 -> 3 -> NULLhead = Node(1)head.next = Node(2)head.next.next = Node(3)
print("Original: ", end="")print_list(head)
head = reverse(head)
print("Reversed: ", end="")print_list(head)The output of the above code will be:
Original: 1 -> 2 -> 3 -> NULLReversed: 3 -> 2 -> 1 -> NULLβ±οΈ Time and Space Complexity
Here is how the two approaches compare.
| Approach | Time | Space |
|---|---|---|
| Copy into array, rebuild | O(n) | O(n) |
| Three pointers (in place) | O(n) | O(1) |
Both walk the list once, so both are O(n) time. But the three-pointer way uses no extra list. That O(1) space is what the interviewer wants to hear.
Tip
If the interviewer asks for the recursive version, the idea is the same. You walk to the end, then flip each arrow on the way back. But recursion uses the call stack, so its space is O(n), not O(1). The iterative three-pointer way is the cleaner answer when they care about memory.
π§© Key Takeaways
- β The real test is moving pointers without losing the rest of the list.
- β
Always save
nextbefore you flipcurr.next, or you cut off the chain. - β The three-pointer walk gives O(n) time and O(1) space, which is the best you can do.
- β
When the loop ends,
previs the new head, so returnprev, nothead. - β Practice drawing the arrows on paper. It makes the pointer steps easy to understand.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
Why do we save curr.next into a separate pointer before flipping the arrow?
Why: Once curr.next points back to prev, the original forward link is gone, so we must save it first.
- 2
What does prev point to when the while loop finishes?
Why: curr reaches the end and becomes NULL, leaving prev on the last node touched, which is the new head.
- 3
What is the space complexity of the iterative three-pointer reversal?
Why: It only uses three pointers no matter how long the list is, so space stays constant.
- 4
What is the starting value of prev before the loop begins?
Why: prev starts as NULL because the first node will become the last node, and the last node points to NULL.