patternDSA/In-place Reversal
Core Pattern → Pattern 12

In-place Reversal of a Linked List

Three pointers. Four lines. Zero extra memory. Reverse any portion of a linked list by redirecting .next pointers in a single pass.

Frequency:★★★★☆
·~30 min·Intermediate·5 problems
The Core Shock

Copy values to reverse — O(n) space. Redirect pointers in-place — O(1) space

Copy + Reverse
O(n) space
Collect all vals in array, reverse, overwrite
In-place Reversal
O(1) space
3 pointer variables — no array needed ever

The insight: you don't need to move data — you only need to flip pointers. Each node's .next is just a variable. Change it to point backward instead of forward. Three pointers track where you are, where you came from, and where you're going.

Two Reversal Types

Every in-place reversal problem is one of these two shapes.

Full Reversal

Reverse the entire list. prev starts as None (new tail → None). When curr reaches None, prev is the new head. 4 lines in the loop body.

Test: Ask: 'Reverse the whole list or check palindrome?' → Full reversal.
Reverse a LinkedListPalindrome Check (2nd half)Reorder List
Sub-list Reversal

Reverse only nodes p to q. Three phases: walk to p-1, reverse q-p+1 nodes, stitch back. Save connection_before and last_node_of_sublist before starting.

Test: Ask: 'Reverse a portion / every K nodes / rotate?' → Sub-list reversal.
Reverse Sub-listReverse every KReverse alternating KRotate LinkedList

The 3-Step Framework

The same 4-step inner loop works for every reversal — memorize it once.

01
Initialize: prev=None, curr=head

prev represents the already-reversed portion (starts empty → None). curr is the node being processed. Always start both at the same end — prev=None, curr=head for full reversal.

prev = None
curr = head
prev=None ensures the original head (which becomes the new tail) points to None after reversal. Never initialize prev=head.
02
The 4-line inner loop — memorize this exactly

4 operations in order, every time: (1) save next_node = curr.next, (2) flip curr.next = prev, (3) advance prev = curr, (4) advance curr = next_node. Missing or reordering any step loses a pointer forever.

next_node = curr.next   # 1. save
curr.next = prev        # 2. flip
prev = curr             # 3. advance prev
curr = next_node        # 4. advance curr
Step 1 must come before step 2 — flipping curr.next first loses the only reference to the rest of the list. The order is non-negotiable.
03
Sub-list: save 2 connection points before reversing

For sub-list reversal: before starting the reversal, save (1) last_node_of_first_part (node at p-1) and (2) last_node_of_sub_list (node at p, which becomes the tail). After reversing, reconnect both.

last_of_first = prev     # node at p-1
last_of_sub   = curr     # node at p (becomes tail)
# ... reverse ...
last_of_first.next = prev  # connect
last_of_sub.next = curr    # connect rest
If p=1, last_of_first is None — handle this case by updating head = prev instead of last_of_first.next = prev.

Pattern Recognition

Spot the reversal pattern before the interviewer finishes the sentence.

Use In-place Reversal When
"Reverse a linked list"
"Reverse sub-list from p to q"
"Reverse every K elements"
"Reverse alternating K-element sub-lists"
"Rotate a linked list"
Palindrome check on linked list
"Reorder list: first + last interleaved"
O(1) space required on linked list
Watch Out For
p=1 → no before-connection, update head directly
p=q → single node, return head unchanged
k > list length → reverse what's left (or don't)
Doubly linked list → must update .prev too
Rotation by k: k %= n first to avoid full loops
Stack approach is O(n) space — not in-place
Recursive reversal is O(n) call stack — not O(1)
Must save next_node BEFORE flipping — order matters