EasyLinked List

Reverse Linked List โ€” Solution

Problem

Given a singly linked list, reverse the direction of all its pointers so the last node becomes the head and the original head becomes the tail.

1
โ†’
2
โ†’
3
โ†’
4
โ†’
5
โ†’โˆ…
[1,2,3,4,5]
  • Input: head = [1, 2, 3, 4, 5]
  • Output: [5, 4, 3, 2, 1]
  • Explanation: Every pointer is flipped, so the list now runs from 5 back to 1.

Intuition

The difficulty is that you can only follow pointers forward โ€” once you redirect a node's next pointer to face backward, you'd lose your path to the rest of the list unless you saved it first. The iterative solution carries three positions at once: where you've been (prev), where you are (current), and where you're going (next_node), allowing you to flip current without losing the tail.

Approach 1 โ€” Iterative

Walk the list one node at a time, flipping each next pointer to face the previous node before advancing.

  1. Initialize prev = None and current = head.
  2. While current is not null, save next_node = current.next before overwriting anything.
  3. Redirect current.next = prev to flip the pointer backward.
  4. Advance prev to current and current to next_node.
  5. Return prev โ€” it holds the new head once current falls off the end.
1def reverseList(head):
2    prev = None
3    current = head
4    while current:
5        next_node = current.next  # must save before overwriting
6        current.next = prev       # flip the pointer backward
7        prev = current
8        current = next_node
9    return prev

Time: O(n) โ€” each node is visited exactly once.
Space: O(1) โ€” only three pointer variables regardless of list length.

Approach 2 โ€” Recursive

Recurse all the way to the tail, then redirect each node's former successor back at it on the way back up.

  1. Base case: if head is null or head.next is null, return head (single node is already reversed).
  2. Recurse into head.next to reverse the rest of the list; capture the returned new head.
  3. head.next.next = head makes the node that was after head point back at head.
  4. head.next = None cuts head's forward link to prevent a cycle.
  5. Return new_head unchanged through every recursive frame.
1def reverseList(head):
2    if not head or not head.next:
3        return head
4    new_head = reverseList(head.next)
5    head.next.next = head  # redirect former successor back at head
6    head.next = None       # cut the forward link to prevent a cycle
7    return new_head

Time: O(n) โ€” one recursive call per node.
Space: O(n) โ€” one stack frame per node deep in the call stack.

Complexity Summary

ApproachTimeSpaceWhen to use
IterativeO(n)O(1)Default choice; constant space is safer for long lists
RecursiveO(n)O(n)When recursive style is preferred and list length is bounded

Common Mistakes

  • Not saving next_node before redirecting โ€” setting current.next = prev immediately orphans the rest of the list; you must capture current.next in a temporary variable first.
  • Returning current instead of prev โ€” current is None when the loop exits; prev holds the new head and is the correct return value.
  • Forgetting head.next = None in the recursive version โ€” without it, the original head still points forward and creates a cycle in the reversed list.
  • Initializing prev = head instead of None โ€” when the first node is processed, current.next = prev makes it point at itself, corrupting the list.
  • Using while current.next instead of while current โ€” the loop stops one node too early, leaving the last node unflipped and disconnected from the reversed portion.

Related Problems

Ready to practice? Try it on SkillFlow

Adaptive problems, AI follow-up interviews, and a skill score that shows exactly where you need to improve.

Practice This Problem โ†’