Reverse Nodes in k-Group takes the classic "reverse a linked list" move and applies it in fixed-size chunks. It is a favorite because it forces you to be precise about pointers: you reverse a block, then stitch it back into the list without losing the rest.
Problem. Given the head of a linked list, reverse the nodes k at a time and return the new head.
If the number of nodes is not a multiple of k, the leftover nodes at the end stay in their original
order.
Example: list = 1 -> 2 -> 3 -> 4 -> 5, k = 2 → 2 -> 1 -> 4 -> 3 -> 5. The block (1, 2) reverses to
2 -> 1, the block (3, 4) reverses to 4 -> 3, and the lone 5 is left alone.
The slow way first
You could copy the values into an array, reverse them in groups, then rebuild a brand-new list. That works and is easy to reason about, but it uses O(n) extra space and quietly ignores the point of the exercise — which is to manipulate the pointers in place.
The question to ask: can I reverse just one block at a time, in place, and reconnect it cleanly? If I can reverse a block of k nodes and know where its tail should point, I can repeat that for every block.
The idea: reverse one block, then recurse
Walk forward k steps first. If you cannot take k full steps, the remaining block is too short — leave it as-is and return its head untouched. Otherwise, reverse the next k nodes using a three-pointer walk (prev, cur, nxt), where prev is seeded with the already-reversed remainder of the list. The new head of the block becomes the head you return.
The key insight: by reversing the rest of the list first and passing its head in as prev, each block's tail automatically links to the next reversed block. No separate stitching step is needed.
Walk through it
Step through the animation. First we confirm two nodes (1, 2) remain — a full block. Then cur walks the block: node 1 flips to point past the block, prev and cur advance, and node 2 flips to point at 1. The block re-seats as 2 -> 1, and the same routine runs on 3 -> 4 -> 5, reversing 3, 4 and leaving 5 alone.
Pseudocode
count k nodes starting at head
if fewer than k nodes remain:
return head # short block: leave it untouched
prev = reverse the rest of the list (start at the (k+1)-th node)
cur = head
repeat k times: # reverse this block, seeded with prev
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
return prev # prev is the block's new headThe Python solution
def reverse_k_group(head, k):
node = head
count = 0
while node and count < k:
node = node.next
count += 1
if count < k:
return head
prev = reverse_k_group(node, k)
cur = head
for _ in range(k):
nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
return prev- The first
whileloop walksksteps to see whether a full block exists;nodelands on the node just after the block. - If
count < kwe hit a short trailing block, so wereturn headand leave it in original order. prev = reverse_k_group(node, k)reverses everything after this block first, soprevis the head we should link our reversed block onto.- The
forloop is the standard in-place reversal: savenxt, pointcur.nextback toprev, then slide both pointers forward. - After
kflips,previs the new head of the reversed block, so wereturn prev.
Complexity
| Case | Time | Notes |
|---|---|---|
| Copy to array, rebuild | O(n) (moderate) | easy but O(n) extra space |
| In-place block reversal (this solution) | O(n) (moderate) | each node touched a constant number of times |
O(n / k) (moderate)Every node is visited a constant number of times, so the time is O(n). The recursion adds one stack frame per block, giving O(n / k) space; an iterative version brings that down to O(1).
When this pattern shows up
When a list problem says "in groups of k," "every other node," or "reverse a sublist," reach for the
three-pointer reversal (prev, cur, nxt) and think carefully about what each block's tail must point
to. Reversing the remainder first is a clean way to avoid fiddly re-stitching.
The trap is the short trailing block. You must count k nodes before reversing and bail out if fewer
than k remain — otherwise you reverse a partial block and break the "leftover stays in order" rule.
Practice
For list = 1 -> 2 -> 3 -> 4 -> 5 and k = 3, what is the result?
1. What happens to a trailing block with fewer than k nodes?
2. Why does this solution reverse the rest of the list before reversing the current block?
3. In the three-pointer reversal, what is nxt used for?
4. What is the time complexity of the in-place solution?