Reverse Nodes in k-Group: Chunked Linked List Reversal
Reverse Nodes in k-Group is LeetCode problem 25 (hard). Given the head of a linked list, reverse the nodes of the list k at a time, and return the modified list.
k is a positive integer and is less than or equal to the length of the linked list. If the number of remaining nodes is not a multiple of k, leave them in their original order.
You may not alter the values in the nodes. Only the nodes themselves may be changed.
Example: [1, 2, 3, 4, 5] with k = 2 produces [2, 1, 4, 3, 5]. With k = 3 it produces [3, 2, 1, 4, 5].
This is a hard problem because it combines two things that are each tricky on their own: reversing a linked list segment in place, and stitching those reversed segments back together without losing references.
The approach
The algorithm breaks down into a repeating cycle of three operations:
- Count k nodes ahead. Starting from the current position, walk forward k steps. If you cannot reach k nodes, the remaining segment is too short to reverse. Leave it as-is and stop.
- Reverse the k-node chunk. Use the standard in-place linked list reversal on exactly k nodes. The old head of the chunk becomes the tail, and the old tail becomes the new head.
- Connect to the previous group. The node before the chunk (
prev) needs itsnextpointer updated to point at the new head (old tail) of the reversed chunk. The new tail (old head) of the reversed chunk needs to point at whatever comes after the chunk.
Then advance prev to the new tail (old head of the chunk) and repeat.
A dummy node before the head gives you a stable anchor. The first group reversal changes the head of the list, and the dummy node handles that without any special case.
Visual walkthrough
Trace through reversing in groups of k = 3 on the list 1 -> 2 -> 3 -> 4 -> 5. The dummy node (labeled "d") sits before the list. Watch how the algorithm counts ahead, reverses, connects, and then checks the next group.
Setup: Create a dummy node. Check if k=3 nodes exist ahead.
prev = dummy. Count k=3 nodes forward from prev to find kth. Three nodes exist, so this group will be reversed.
Reverse group 1: Reverse the 3-node sublist in place.
Nodes 1, 2, 3 are reversed to 3, 2, 1. prev.next now points to 3 (the old tail). Node 1 (old head) links to node 4. prev advances to node 1.
Check group 2: Count k=3 nodes ahead from prev. Only 2 remain.
Starting from prev (node 1), only 2 nodes remain. That is fewer than k=3, so they stay as-is. Algorithm stops.
Done: Return dummy.next. The first group is reversed, the remainder is untouched.
Final list: 3 -> 2 -> 1 -> 4 -> 5 -> null. The first k=3 nodes are reversed. Nodes 4 and 5 remain in original order.
The key insight: after reversing a group, the old head of that group is now the tail. That tail becomes prev for the next iteration, and its next pointer will be updated to point at the new head of the next reversed group.
The solution
def reverseKGroup(head, k):
dummy = ListNode(0)
dummy.next = head
prev = dummy
while True:
kth = prev
for _ in range(k):
kth = kth.next
if not kth:
return dummy.next
group_next = kth.next
curr = prev.next
nxt = curr.next
for _ in range(k - 1):
curr.next = nxt.next
nxt.next = prev.next
prev.next = nxt
nxt = curr.next
prev = curr
return dummy.next
The inner loop runs k - 1 times, not k times. Reversing k nodes requires k - 1 pointer swaps. Each iteration moves one node from ahead of curr to the front of the group.
How the inner loop works
The reversal inside each group uses a technique where you repeatedly take the node after curr and move it to the front of the group. After the inner loop finishes, curr has moved from the front to the back of the group (it is now the tail), and prev.next points to the node that was originally at the back (now the head).
Here is what happens in each iteration of the inner loop:
nxt = curr.nextgrabs the next node to be movedcurr.next = nxt.nextdetachesnxtfrom its current positionnxt.next = prev.nextattachesnxtat the front of the groupprev.next = nxtupdates the entry point to the group
This is a variant of the standard linked list reversal that works within a bounded window. Instead of using prev/curr/next pointers that all advance forward, you keep curr stationary and repeatedly pull the next node to the front.
Complexity analysis
| Metric | Value |
|---|---|
| Time | O(n) |
| Space | O(1) |
Every node is visited a constant number of times. The counting pass walks through each node once. The reversal pass touches each node in the group once. No extra data structures are allocated beyond a few pointer variables.
The building blocks
This problem is built from two core building blocks:
In-place linked list reversal. The inner loop is the same pointer-swapping technique from Reverse Linked List, constrained to exactly k nodes instead of the entire list. If you can reverse a full linked list, you already know the core operation. The new part is knowing when to stop (after k - 1 swaps) and how to connect the reversed segment back into the surrounding list.
Group processing with a lookahead check. Before reversing, you walk k nodes ahead to confirm the group is complete. This count-then-act pattern prevents you from partially reversing a group that should remain untouched. The dummy node and prev pointer give you a uniform way to connect each reversed group without special-casing the first group.
Edge cases
k = 1. The counting loop always succeeds (one node exists), but the inner loop runsk - 1 = 0times. No pointers change. The list is returned as-is. Correct.kequals the list length. The entire list is one group. It reverses completely. The counting loop finds exactly k nodes, the inner loop reverses all of them, and the next counting pass hits null immediately. Correct.- Remaining nodes fewer than k. After reversing some groups, the counting loop reaches null before completing k steps. It returns
dummy.nextimmediately. The remaining nodes stay in their original order. Correct. - Single node list. If k is 1, nothing changes. If k is greater than 1, the counting loop hits null on the first pass. Either way, the single node is returned. Correct.
- Two nodes with
k = 2. This reduces to Swap Nodes in Pairs. The algorithm handles it correctly as a single group of two.
From understanding to recall
You understand the counting pass, the inner reversal loop, and how prev stitches groups together. But can you write this solution from scratch without hesitation?
The tricky part is the four pointer assignments inside the inner loop. Which pointer gets updated first? What does curr point to after the loop? Where does prev advance to? These details matter, and getting one wrong means a broken list or an infinite loop.
The only way to make the four-line inner loop automatic is repetition. Type the solution from memory today, again in three days, again next week. By the fourth rep, the reversal pattern and the group-connection logic will feel natural.
Related posts
- Reverse Linked List - The foundational in-place reversal technique that this problem uses inside each group
- Swap Nodes in Pairs - The k=2 special case of this problem, using a simpler three-pointer swap per pair