Lesson 20 — Reversing a Linked List

~20 minutes · prev/curr/next · Python

Tonight's linked-list problem is Reverse Linked List. Interviewers love it because it is small, visual, and unforgiving: one pointer update in the wrong order can lose the rest of the list. The win is learning a safe order you can say out loud before you code.

The invariant

Reversal is re-aiming one arrow per step; save next before you break the link so you don't lose the rest.

A singly linked list is a chain of nodes where each node points to the next one (Wikipedia: linked list). Reversing the list does not require new nodes. It requires changing each next arrow so it points backward instead of forward.

Reverse Linked List: the heavy way first

The brute-force version is to copy every node into an array, then reconnect those nodes from right to left. It is O(n) time and O(n) space:

def reverse_list(head):
    nodes = []
    cur = head
    while cur:
        nodes.append(cur)
        cur = cur.next
    for i in range(len(nodes) - 1, 0, -1):
        nodes[i].next = nodes[i - 1]
    nodes[0].next = None
    return nodes[-1]

This works, but the array is the crutch. The interview version wants the same O(n) time with O(1) extra space: keep only three names — prev, curr, and nxt — and move the boundary one node at a time. The LeetCode statement defines the target behavior here: return the head of the reversed list (LeetCode: Reverse Linked List).

Reverse Linked List: the pointer way

At any moment, prev is the head of the reversed prefix, and curr is the first node not fixed yet. Save curr.next before changing it, because that arrow is your only path to the untouched suffix.

One safe linked-list reversal step The current node saves its next node before its next arrow is redirected backward to the previous node. Before changing an arrow: save nxt first Key insight: save the forward path, then re-aim curr.next backward. None 1 2 3 prev curr nxt after saving nxt, set curr.next = prev

One loop step: protect the untouched suffix with nxt, then turn curr's arrow around.

def reverseList(head):
    prev, curr = None, head
    while curr:
        nxt = curr.next      # save the untouched suffix
        curr.next = prev     # re-aim this arrow backward
        prev = curr          # grow the reversed prefix
        curr = nxt           # move to the next untouched node
    return prev              # new head

Trace three nodes on paper: 1 → 2 → 3. After the first loop, 1 points to None. After the second, 2 → 1. After the third, 3 → 2 → 1. The code is short because the invariant is doing the work.

Transfer: same move, new costume

Palindrome Linked List often uses this same primitive: find the middle, reverse the second half, then compare both halves.

Before opening the reveal: if the second half starts at slow, what helper should you call, and what must be true while it runs? Say the invariant out loud first.

Your prediction first — then open.

Call the same reversal helper on slow. While it runs, prev is the reversed prefix of the second half, curr is the first untouched node, and nxt preserves the rest before each arrow changes.

What the trade buys you

ApproachTimeSpace
Array reconnectO(n)O(n)
prev/curr/next pointersO(n)O(1)

The speed is the same. The difference is control: the pointer version keeps the whole operation in the list itself.

Practice — answer before you scroll past

1. What must you save before changing curr.next?

2. After one loop step, what does prev point to?

3. Spot the bug in this loop:

while curr:
    curr.next = prev
    nxt = curr.next
    prev = curr
    curr = nxt

4. Which future task uses this same primitive?

Your move (tonight)

Solve Reverse Linked List in your Notion tracker with the cycle — predict → attempt → compare → encode.

  1. Predict: draw 1 → 2 → 3, name prev, curr, and nxt, then state the invariant.
  2. Attempt: code the O(1)-space version from a blank editor.
  3. Compare: watch the primary source below only after the attempt.
  4. Encode: write one Notes line: what must be saved before each arrow changes?
One primary source

Watch NeetCode — Reverse Linked List after your attempt, as the compare step. Listen for the moment he saves the next pointer before redirecting the current one.