Reverse Linked List
Given the head of a singly linked list, reverse it so the original last node becomes the head and every next pointer points the opposite way, then return the new head. Rewire the existing nodes in place — no new list is built. An empty list returns null; a single-node list returns itself unchanged.
- The number of nodes in the list is in the range [0, 5000]
- -5000 <= Node.val <= 5000
head = [1,2,3,4,5][5,4,3,2,1]head = [1][1]head = [][]We must reverse a singly linked list: the node that was last becomes the head, and every arrow that pointed forward now points backward. We want to do it in place — rewiring the existing nodes — rather than copying values into a fresh list.
"Make each node point to the one before it" sounds trivial until you notice the phrase the one before it. A singly linked list stores only forward arrows; a node has no idea who precedes it. So as we walk forward, we must carry the predecessor ourselves. And there is a sharper trap: the instant we flip a node's arrow to point back at its predecessor, we overwrite the very pointer that told us where the rest of the list was. Flip too early and the unvisited tail floats off, unreachable — the exact severed-chain failure warned about in Linked List Traversal. Every correct reversal comes down to one requirement: flip this link without losing the next one.
(Recursion, or an explicit stack, can dodge the manual bookkeeping — but both spend O(N) memory on frames or stack entries, and the whole point of this problem is the O(1)-space in-place version.)
Picture the walk with the list split in two: everything behind you is already reversed, everything ahead is still original. You hold the head of the reversed-so-far part in a pointer prev, and you stand on the next original node with curr. One step means: detach curr from the original chain and glue it onto the front of the reversed part. Do that N times and the whole list migrates, node by node, from "ahead, original" to "behind, reversed." prev always names the current head of the growing reversed portion — so when nothing remains ahead, prev is the head of the entire reversed list.
Each step needs three references: prev (head of the reversed part, starting at null — the reversed empty list), curr (current node), and a temporary next_temp (a cache of the rest, so flipping curr doesn't lose it).
prev = None
curr = head
while curr:
next_temp = curr.next # 1. SAVE the rest before we destroy the link
curr.next = prev # 2. FLIP: point current back at the reversed part
prev = curr # 3. the reversed part now starts at curr
curr = next_temp # 4. advance into the still-original tail
return prev # curr is null; prev is the new headcurr.next — the only link to the unreversed tail. Without stashing it in next_temp first, that tail is lost the instant we flip, and the loop has nothing to advance into. Cache, then flip, then advance both pointers: that four-line dance, in that order, is reversal.Why does returning prev give the right head? When the loop ends, curr has walked off the end and is null, while prev holds the node we flipped most recently — the original last node. Every node's arrow now points at its original predecessor, so the original tail, now first, is exactly prev.
And the empty list: curr = head = null, the loop body never runs, we return prev = null — correct, with no special case.
Strip this problem away and a reusable unit remains: walk a chain while re-pointing each node at the node behind it, held together by the cache-flip-advance order. You will reuse it unchanged as an inner routine — reverse the second half of a list to test a palindrome, reverse a fixed block in Reverse Nodes in k-Group, reverse a sublist between two positions. Three things stay constant every time (the prev/curr/next_temp trio, cache-before-flip, return prev) and only two vary per problem: where the reversal starts and when it stops (the whole list, a group of k, up to a boundary node). Fill those two slots and the rest is this same dance.
One pass, a fixed set of pointers: O(N) time, O(1) space — beating the recursive version's O(N) call stack. Train the reflex: whenever a linked-list task needs the nodes in reverse, or needs to compare the front against the back (which a forward-only list cannot do directly), reach for this in-place reversal instead of copying into an array.
Iterative Reversal
prev = null, curr = head