Reverse Linked List
Problem
head of a singly linked list, flip the direction of every
link so the last node becomes the first, and return the new head. An empty list
stays empty.[1,2,3,4,5]Output[5,4,3,2,1][1,2]Output[2,1][]Output[]0 ≤ n ≤ 5000 · -5000 ≤ Node.val ≤ 5000 · Follow-up: solve it both iteratively and recursively.
Try it yourself
class Solution {
public ListNode reverseList(ListNode head) {
}
}
next arrow around.
Before flipping curr.next, save it, or you lose the rest of the list.Instinct Nodes joined by next pointers and the task is to reverse, splice, merge, reorder or remove in place - grab a dummy head and rewire pointers carefully.
Memory hack Save next, flip, step - never let go of a rope before you've grabbed the next one.
Open the Linked List Techniques guide →Approaches
Brute ForceStack of Nodes, then Relink
O(n)Space O(n)A stack reverses order for free: push every node, then pop them one by one and
chain them in pop order. The last popped node (old head) must get
next = null, otherwise the list ends in a cycle.
public ListNode reverseList(ListNode head) { if (head == null) return null; Deque<ListNode> stack = new ArrayDeque<>(); for (ListNode c = head; c != null; c = c.next) stack.push(c); ListNode newHead = stack.pop(), cur = newHead; while (!stack.isEmpty()) { cur.next = stack.pop(); cur = cur.next; } cur.next = null; // old head is now the tail return newHead; }
Obvious and correct, but stores every node a second time.
BetterRecursion (Reverse the Rest First)
O(n)Space O(n)Trust the recursion: reverseList(head.next) returns the reversed tail,
whose last node is still head.next. Hook head after it
(head.next.next = head) and cut head.next.
public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode newHead = reverseList(head.next); head.next.next = head; // the node after head now points back head.next = null; return newHead; }
Elegant and in-place, but n stack frames — may overflow for long lists.
OptimalIterative Three Pointers
O(n)Space O(1)Keep prev (already reversed part) and curr (rest).
Each step: save next, point curr back at prev,
then slide both forward. When curr is null, prev is the new head.
public ListNode reverseList(ListNode head) { ListNode prev = null, curr = head; while (curr != null) { ListNode next = curr.next; // save the rest curr.next = prev; // flip the arrow prev = curr; curr = next; } return prev; }
Dry run[1,2,3,4]
- start1c234prev=null
- step 11p2c341→null
- step 212p3c42→1→null
- step 3123p4c3→2→1
- step 41234pcurr=null, return 4 ✔
One pass, constant memory — the textbook answer.
At a glance
| Level | Approach | Time | Space |
|---|---|---|---|
| Brute Force | Stack of Nodes, then Relink | O(n) | O(n) |
| Better | Recursion (Reverse the Rest First) | O(n) | O(n) |
| Optimal | Iterative Three Pointers | O(n) | O(1) |
- Overwriting
curr.nextbefore saving it — the rest of the list is lost. - Returning
headorcurrinstead ofprev. - Recursive version: forgetting
head.next = nullcreates a 2-node cycle.
- Draw 3 boxes and arrows; narrate save → flip → advance.
- Offer both versions (it is the stated follow-up) and compare stack usage.
- Test aloud on empty, single-node and two-node lists.