Reverse a Linked List

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 -> NULL
Output: 3 -> 2 -> 1 -> NULL

See, 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 as NULL.
  • curr β€” the node we are looking at right now.
  • next β€” a safety pointer that remembers what comes after curr.

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 curr

First we save next so we do not lose node 2:

next = 2

Then we flip curr’s arrow to point back at prev:

NULL <- 1 2 -> 3 -> NULL

Now we slide both pointers one step forward. prev becomes curr, and curr becomes next:

NULL <- 1 2 -> 3 -> NULL
^ ^
prev curr

We 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

  1. Set prev = NULL and curr = head.
  2. While curr is not NULL, do the next steps.
  3. Save next = curr.next so the rest of the list is safe.
  4. Point curr.next back to prev.
  5. Move prev = curr and curr = next.
  6. When the loop ends, prev is the new head. Return it.

Now here is the code that builds a list, reverses it, and prints both.

reverse_list.py
# One node of the list
class Node:
def __init__(self, data):
self.data = data
self.next = None
# Reverse the list and return the new head
def 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 -> NULL
head = 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 -> NULL
Reversed: 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 next before you flip curr.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, prev is the new head, so return prev, not head.
  • βœ… 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. 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. 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. 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. 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.

πŸš€ What’s Next?

Share & Connect