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]
- 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.
- Initialize
prev = Noneandcurrent = head. - While
currentis not null, savenext_node = current.nextbefore overwriting anything. - Redirect
current.next = prevto flip the pointer backward. - Advance
prevtocurrentandcurrenttonext_node. - Return
prevโ it holds the new head oncecurrentfalls 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 prevTime: 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.
- Base case: if
headis null orhead.nextis null, returnhead(single node is already reversed). - Recurse into
head.nextto reverse the rest of the list; capture the returned new head. head.next.next = headmakes the node that was afterheadpoint back athead.head.next = Nonecutshead's forward link to prevent a cycle.- Return
new_headunchanged 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_headTime: O(n) โ one recursive call per node.
Space: O(n) โ one stack frame per node deep in the call stack.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Iterative | O(n) | O(1) | Default choice; constant space is safer for long lists |
| Recursive | O(n) | O(n) | When recursive style is preferred and list length is bounded |
Common Mistakes
- Not saving
next_nodebefore redirecting โ settingcurrent.next = previmmediately orphans the rest of the list; you must capturecurrent.nextin a temporary variable first. - Returning
currentinstead ofprevโcurrentisNonewhen the loop exits;prevholds the new head and is the correct return value. - Forgetting
head.next = Nonein the recursive version โ without it, the original head still points forward and creates a cycle in the reversed list. - Initializing
prev = headinstead ofNoneโ when the first node is processed,current.next = prevmakes it point at itself, corrupting the list. - Using
while current.nextinstead ofwhile currentโ the loop stops one node too early, leaving the last node unflipped and disconnected from the reversed portion.
Related Problems
Reverse Linked List IIโ reverse only the subrange [left, right] using the same pointer-flip techniquePalindrome Linked Listโ reverses the second half of the list to compare against the first halfReorder Listโ reverses the back half then interleaves it with the front halfMiddle of the Linked Listโ fast/slow pointer setup that typically precedes a reversal stepReverse Nodes in k-Groupโ applies this exact reversal repeatedly to consecutive chunks of k nodes