150NeetCode 150

35.Reverse Linked List

EasyBlind 75Linked List ยท 1/11

Problem

Given the head of a singly linked list, reverse the list in place and return the new head.

After reversing, the node that used to be last becomes the first, and every next pointer points to the node that used to come before it.

Examples

Input:  head = [1, 2, 3, 4, 5]
Output: [5, 4, 3, 2, 1]
Explanation: Every arrow flips direction; node 5 becomes the new head.
Input:  head = [1, 2]
Output: [2, 1]
Input:  head = []
Output: []
Explanation: An empty list reversed is still empty.

Constraints

  • The number of nodes in the list is in the range [0, 5000].
  • -5000 <= Node.val <= 5000

๐Ÿ’ก Key Insight

Reversing a list means flipping each next pointer to point backwards. If you walk the list once while remembering the previous node, you can flip one arrow at a time โ€” the only trick is to save curr.next before overwriting it, otherwise you lose the rest of the list.

Brute Force (Stack)

TimeO(n)SpaceO(n)

Intuition

A stack is last-in, first-out, so pushing every node and then popping them gives the nodes in reverse order. We then relink them in the popped order.

Algorithm

  1. Push every node onto a stack.
  2. Pop the top node โ€” it is the new head.
  3. Keep popping, setting tail.next = popped and advancing tail.
  4. Set the final tail.next = null (the old head still points to the old second node, which would create a cycle).
  5. Return the new head.

Visualization

list:  1 -> 2 -> 3
stack (top on right): [1, 2, 3]

pop 3 -> head = 3
pop 2 -> 3 -> 2
pop 1 -> 3 -> 2 -> 1 -> null   (must clear 1.next!)

Code

java
import java.util.ArrayDeque;
import java.util.Deque;

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null) {
            return null;
        }
        Deque<ListNode> stack = new ArrayDeque<>();
        for (ListNode node = head; node != null; node = node.next) {
            stack.push(node);
        }
        ListNode newHead = stack.pop();
        ListNode tail = newHead;
        while (!stack.isEmpty()) {
            tail.next = stack.pop();
            tail = tail.next;
        }
        tail.next = null; // old head is now the tail; break the old link
        return newHead;
    }
}

Complexity

  • Time: O(n) โ€” every node is pushed and popped once.
  • Space: O(n) โ€” the stack holds all n nodes.

Complexity Comparison

Approach Time Space
Stack O(n) O(n)
Recursion O(n) O(n)
Iterative Pointer Reversal O(n) O(1)

Common Pitfalls

  • Overwriting curr.next before saving it โ€” the rest of the list becomes unreachable.
  • Returning curr instead of prev at the end โ€” curr is always null when the loop stops.
  • In the recursive version, forgetting head.next = null, which leaves a 2-node cycle between the old first and second nodes.
  • In the stack version, not clearing the last node's next, which also creates a cycle.
  • Not handling head == null โ€” every approach must return null for an empty list.