Reverse Linked List

EasyLinked ListLinked ListRecursion

Problem

You are given the head of a singly linked list. Return the head of the list with the order of nodes reversed, so the last node becomes first and the first becomes last, without changing the node values themselves.

Example. The list 1 -> 2 -> 3 -> 4 -> 5 becomes 5 -> 4 -> 3 -> 2 -> 1.

Key idea

A singly linked list only stores a forward pointer on each node, so reversing it means flipping every node's next pointer to point at the node before it instead of the node after it. The naive instinct is to read off the values and rebuild a new list, which works but wastes an extra array and a second pass.

The efficient approach walks the list once with three tracked references: the current node, the node before it (initially none), and a saved pointer to what comes next. At each step, save the current node's next before overwriting it, point the current node backward at the previous node, then slide all three references forward by one. When the walk runs out of nodes, the last node visited is the new head. The same idea can be expressed recursively: reverse everything after the current node first, then fix the current node's link, trading the iterative walk's O(1) space for stack frames proportional to list length.

Solution

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

function reverseList(head: ListNode | null): ListNode | null {
  let prev: ListNode | null = null;
  let curr = head;

  while (curr !== null) {
    const next = curr.next; // save next before curr.next is overwritten
    curr.next = prev; // flip the pointer to face backward
    prev = curr;
    curr = next;
  }

  return prev; // prev holds the old tail, now the new head
}

Complexity

  • Time: O(n). Every node is visited exactly once.
  • Space: O(1) iteratively, since only a few pointers are tracked; O(n) if implemented recursively, due to the call stack.

Watch out for

  • Save the next node before rewriting the current node's pointer: overwrite first and the rest of the list becomes unreachable.
  • The original head must end up pointing to nothing, or the reversed list will dangle into whatever followed it before reversal.
  • An empty or single-node list should be returned unchanged, without extra branching.

Pattern

This is the foundational pointer-rewiring pattern for linked lists: track a small, fixed window of neighboring references while walking once. The same prev/curr/next mechanics reappear in partial reversals, palindrome checks, and any problem that reorders nodes in place.

Related questions