Reverse a Linked List

Three-Pointer Iterative Reverse Runs in O(n) Time and O(1) Space

Reverse a Linked List

Master in-place linked list reversal with the classic three-pointer iterative algorithm and its elegant recursive counterpart.

5 min read Level 2/5 #dsa#linked-list#reverse
What you'll learn
  • Reverse a singly linked list in-place using prev, curr, and next pointers
  • Implement the recursive reversal and understand its O(n) call-stack cost
  • Identify when iterative reversal is preferred over the recursive version

Reversing a linked list means flipping every next pointer so the former tail becomes the new head. The challenge is doing it in place without losing your position in the list.

Node Class

class ListNode {
  constructor(val = 0, next = null) {
    this.val = val;
    this.next = next;
  }
}

Iterative Three-Pointer Approach

Keep three variables as you walk the list:

  • prev — the node that should follow curr after reversal (starts null)
  • curr — the node being processed right now
  • next — a temporary save of curr.next before it is overwritten
function reverseList(head) {
  let prev = null;
  let curr = head;

  while (curr !== null) {
    const next = curr.next;   // 1. save next
    curr.next = prev;          // 2. flip pointer
    prev = curr;               // 3. advance prev
    curr = next;               // 4. advance curr
  }

  return prev;  // prev is the new head when curr reaches null
}

// Example
// Before: 1 → 2 → 3 → null
// After:  3 → 2 → 1 → null

Walk through a three-node list to build intuition:

Stepprevcurrcurr.next (after flip)
startnull1
1121
2232
33null

When the loop ends prev points to the old tail — the new head.

Recursive Approach

The recursive version trusts the call stack to “remember” the suffix while it reverses the suffix and then splices the current node at the back.

function reverseListRecursive(head) {
  // Base case: empty list or single node
  if (head === null || head.next === null) return head;

  // Reverse the rest of the list
  const newHead = reverseListRecursive(head.next);

  // head.next still points to the last node of the reversed suffix;
  // make that node point back at head, then cut head's forward link.
  head.next.next = head;
  head.next = null;

  return newHead;
}

Recursion is elegant but uses O(n) call-stack frames. For very long lists this can cause a stack overflow in JavaScript; the iterative version is safer in production.

Complexity

ApproachTimeSpace
IterativeO(n)O(1)
RecursiveO(n)O(n) call stack

Practical Use

Reversal is a building block for many harder problems: reversing a sub-list, checking if a linked list is a palindrome, and reordering lists all rely on the same three-pointer technique.

Up Next

Learn Floyd’s tortoise and hare algorithm for detecting cycles in a linked list — and for finding exactly where the cycle starts.

Cycle Detection →