The in-place reversal of a linked list pattern flips the next pointers of a list (or part of it) one node at a time using three pointers, prev, curr and next, so it runs in O(n) time and O(1) extra space. Reach for it whenever a problem asks you to reverse a list, a sublist between two positions, or every group of k nodes, or to compare or merge the two halves of a list without copying it into an array.
This guide gives you one template, three worked problems (LeetCode 92, 25 and 234, after the 206 template), the edge cases interviewers test, and a practice list. Every code block on this page was run in Python with asserts against a brute-force check before we published it.
When to use the reverse linked list pattern
The signal is almost always in the problem statement. Look for these:
- The input is a singly linked list and the word reverse appears: the whole list, positions
lefttoright, or groups of k. - You need to read the list backward but can only walk forward (palindrome check, twin sums, adding numbers stored most-significant digit first).
- You must reorder nodes (first, last, second, second-to-last...) without building a new list.
- The prompt says O(1) extra space, which rules out pushing values onto a stack or into an array.
- A follow-up asks "can you do it without modifying the values?" The answer is to move pointers, not swap
valfields.
If the problem instead asks you to find a cycle or the middle node, that is the fast and slow pointers pattern. Many medium problems combine the two: find the middle with fast and slow pointers, then reverse the second half in place.
How the in-place reversal of a linked list works
Picture 1 → 2 → 3 → None. You walk the list once. At each node you do four things in a fixed order: save the rest of the list, point the current node backward, then move both pointers one step forward.
| Step | prev | curr | Links after the step |
|---|---|---|---|
| Start | None | 1 | 1 → 2 → 3 |
| After node 1 | 1 | 2 | None ← 1, and 2 → 3 still waiting |
| After node 2 | 2 | 3 | None ← 1 ← 2, and 3 still waiting |
| After node 3 | 3 | None | None ← 1 ← 2 ← 3 |
When curr becomes None, prev points at the old tail, which is the new head. That is why the function returns prev, not curr or the original head.
The Python template
This is the template to memorize. It is also the full solution to Reverse Linked List (LeetCode 206).
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverse_list(head):
prev, curr = None, head
while curr:
nxt = curr.next # 1. save the rest of the list
curr.next = prev # 2. flip this node's pointer
prev = curr # 3. move prev forward
curr = nxt # 4. move curr forward
return prev # prev is the new head
The order of the four lines matters. If you write curr.next = prev before saving curr.next, you lose the rest of the list. Say the order out loud in the interview: "save, flip, advance, advance."
The recursive version
Interviewers sometimes ask for recursion as a follow-up. It is shorter but uses O(n) call-stack space, so it is not O(1) extra space, and on a very long list it can hit CPython's default recursion limit of 1000 frames (check yours with sys.getrecursionlimit()).
def reverse_list_recursive(head):
if head is None or head.next is None:
return head
new_head = reverse_list_recursive(head.next)
head.next.next = head # the node after head now points back to head
head.next = None # head becomes the tail
return new_head
Worked problem 1: Reverse Linked List II (LeetCode 92)
Reverse Linked List II (LeetCode 92) asks you to reverse only the nodes from position left to position right (1-indexed) in one pass.
The idea: walk to the node just before position left (call it before). Then, right - left times, take the node right after the sublist's current tail and move it to the front of the sublist. A dummy node in front of head handles left = 1 without a special case.
def reverse_between(head, left, right):
dummy = ListNode(0, head)
before = dummy
for _ in range(left - 1): # stop at the node before position left
before = before.next
curr = before.next # first node of the sublist; ends up as its tail
for _ in range(right - left):
moved = curr.next # take the next node...
curr.next = moved.next
moved.next = before.next # ...and insert it at the front of the sublist
before.next = moved
return dummy.next
Complexity: O(n) time in one pass, O(1) extra space. The "insert at the front" trick avoids having to reconnect both ends after a separate reversal, which is where most bugs on this problem come from.
Worked problem 2: Reverse Nodes in k-Group (LeetCode 25)
Reverse Nodes in k-Group (LeetCode 25) is the hard version: reverse every consecutive group of k nodes, and leave a final group with fewer than k nodes as it is.
The idea: keep a pointer group_prev to the node before the current group. First check that k nodes exist by finding the k-th node. Then run the standard reversal on the group, with one change: start prev at the node after the group, so the reversed group's tail is already linked to the rest of the list. Finally, hook group_prev to the new group head and move group_prev to the old first node, which is now the group's tail.
def reverse_k_group(head, k):
dummy = ListNode(0, head)
group_prev = dummy
while True:
kth = group_prev
for _ in range(k): # find the k-th node of this group
kth = kth.next
if kth is None:
return dummy.next # fewer than k nodes left: leave them as is
group_next = kth.next
prev, curr = group_next, group_prev.next
while curr is not group_next: # standard reversal, but the tail links to group_next
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
first = group_prev.next # old first node, now the group's tail
group_prev.next = kth # connect the previous part to the new group head
group_prev = first
Complexity: O(n) time, since each node is visited a constant number of times (once to count the group, once to reverse it), and O(1) extra space. A recursive solution is common too, but it uses O(n/k) stack space.
Worked problem 3: Palindrome Linked List (LeetCode 234)
This one combines two patterns and is a favorite "can you do it in O(1) space?" follow-up. The array solution (copy values, compare with the reversed copy) is O(n) space. The in-place answer reuses reverse_list from the template:
- Find the middle with fast and slow pointers.
- Reverse the second half in place with the template.
- Compare the first half and the reversed second half node by node.
- Reverse the second half again so the caller gets the list back unchanged.
def is_palindrome(head):
slow = fast = head
while fast and fast.next: # slow stops at the middle
slow = slow.next
fast = fast.next.next
second = reverse_list(slow) # reverse the second half in place
a, b, ok = head, second, True
while b:
if a.val != b.val:
ok = False
break
a, b = a.next, b.next
reverse_list(second) # restore the input list
return ok
Complexity: O(n) time, O(1) extra space. Step 4 is optional on LeetCode, but mentioning it in an interview shows you think about side effects on input you do not own.
Complexity of linked list reversal problems
| Problem | Approach | Time | Extra space |
|---|---|---|---|
| Reverse Linked List (206) | Iterative three pointers | O(n) | O(1) |
| Reverse Linked List (206) | Recursive | O(n) | O(n) call stack |
| Reverse Linked List II (92) | Dummy node + front insertion | O(n) | O(1) |
| Reverse Nodes in k-Group (25) | Count k, reverse group, reconnect | O(n) | O(1) |
| Palindrome Linked List (234) | Middle + reverse second half | O(n) | O(1) |
| Any of the above | Copy values into an array | O(n) | O(n), usually not accepted as the final answer |
To see how O(1) and O(n) extra memory diverge as inputs grow, try the free Big-O complexity visualizer.
Common bugs and edge cases
- Losing the rest of the list. Always save
curr.nextbefore you overwrite it. - Returning the wrong head. After the loop, the new head is
prev. The originalheadis now the tail. - Leaving a two-node cycle. In the recursive version you must set
head.next = None, or the last two nodes point at each other. - Special-casing position 1. Use a dummy node whenever the head itself might change (problems 92, 25, 24). It removes a whole class of off-by-one bugs.
- Off-by-one on positions. LeetCode 92 is 1-indexed. Walk
left - 1steps from the dummy, notleft. - The short last group. In k-group reversal, count k nodes before reversing; otherwise you reverse a partial group and have to undo it.
- Edge inputs to test out loud: empty list, one node, two nodes,
left == right,k = 1(no change), and k equal to the list length.
Practice list: 8 linked list reversal problems
Do them in this order. Four are covered above; the rest reuse the same template with a twist.
| # | Problem | Difficulty | Twist |
|---|---|---|---|
| 206 | Reverse Linked List | Easy | The template itself |
| 234 | Palindrome Linked List | Easy | Middle + reverse second half |
| 92 | Reverse Linked List II | Medium | Reverse a sublist in one pass |
| 24 | Swap Nodes in Pairs | Medium | k-group reversal with k = 2 |
| 143 | Reorder List | Medium | Middle, reverse second half, then merge alternately |
| 2130 | Maximum Twin Sum of a Linked List | Medium | Reverse second half, walk both halves together |
| 445 | Add Two Numbers II | Medium | Reverse both inputs, add, reverse the result (or use stacks) |
| 25 | Reverse Nodes in k-Group | Hard | Count, reverse, reconnect each group |
Problem numbers and difficulty labels were checked on LeetCode as of October 2026. For where linked lists sit among the other core patterns, see 15 LeetCode patterns for coding interviews and the free coding interview cheat sheet.
How to practice this pattern out loud
Pointer problems go wrong under pressure, not at your desk. Practice explaining the "save, flip, advance" order while you type. In CoPilot Interview's Mock Interview you can include coding questions in your language; it reads each question aloud, scores your spoken answer out of 10 with what to fix and a model answer, and coding questions never auto-submit, so you can think in silence. The browser version at /ai-mock-interview has 113 real questions across 9 tracks, including coding, with nothing to install.
Related patterns to study next: two pointers, sliding window and merge intervals.
Practice linked list questions out loud
Run a free AI mock interview in your browser: answer a coding question, explain your approach, and get feedback on what to tighten.
Try a free AI mock interviewFAQ
What is the in-place reversal of a linked list pattern?
It is a technique that reverses all or part of a singly linked list by flipping each node's next pointer while walking the list once with three pointers (prev, curr and next). It runs in O(n) time and O(1) extra space because no new nodes or arrays are created.
How do you reverse a linked list in place in Python?
Set prev to None and curr to head. While curr is not None: save nxt = curr.next, set curr.next = prev, then move prev = curr and curr = nxt. When the loop ends, prev is the new head, so return prev.
Is the recursive reversal O(1) space?
No. Each recursive call adds a stack frame, so recursion uses O(n) extra space. On long lists it can also hit CPython's default recursion limit of 1000. Use the iterative version when the problem asks for O(1) space.
Why do linked list reversal solutions use a dummy node?
A dummy node placed before the head means the node before the reversed section always exists, even when the reversal starts at the first node. It removes special cases for position 1 and makes returning the new head simple: return dummy.next.
What is the time complexity of Reverse Nodes in k-Group?
O(n) time and O(1) extra space for the iterative solution. Each node is touched a constant number of times: once while counting the group and once while reversing it. A recursive solution is also O(n) time but uses O(n/k) stack space.
Which LeetCode problems use the reverse linked list pattern?
The core ones are Reverse Linked List (206), Reverse Linked List II (92) and Reverse Nodes in k-Group (25). It also appears inside Palindrome Linked List (234), Reorder List (143), Maximum Twin Sum of a Linked List (2130), Swap Nodes in Pairs (24) and Add Two Numbers II (445).