Linked Lists · Linked List Fundamentals

Linked List Group Reversal

Reversing a linked list k nodes at a time by first checking a full group exists, then reversing it and recursively wiring its tail to the (already-processed) rest of the list.

  • 6 min read
  • 11 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: reversing one subrange
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Group reversal reverses a linked list in pieces: k nodes at a time (Reverse Nodes in k-Group), or only the nodes between two positions (Reverse Linked List II). Both reuse the plain reversal loop. The new work is bookkeeping at the edges of each piece. You check that a group is complete before touching it, and you stitch each reversed piece back to the nodes before and after it.

We'll go from simple to more technical:

  1. The pattern: reverse k at a time, only when k nodes remain.
  2. A second flavor: reverse one subrange by repeatedly moving nodes to its front.
  3. Where batch-at-a-time and edit-in-place processing show up.
  4. The stitching bugs, and recursion depth on long lists.

The approach

Reversing a whole list is one loop. In groups of k, a short last group is usually left as it is. So first count ahead: are there k nodes? If not, return the rest unchanged. If so, reverse exactly those k nodes and connect the group's new tail to the rest of the list, which the recursion has already handled.

Reversing 4 -> 9 -> 2 -> 7 -> 5 -> 1 -> 8 in groups of 3:

GroupNodesFull group?After
14 9 2yes2 9 4
27 5 1yes1 5 7
38no, only 1 node8, unchanged

The result is 2 -> 9 -> 4 -> 1 -> 5 -> 7 -> 8. Note the stitch: 4, which was the first group's head, is now its tail and must point to 1, the second group's new head.

Java

ListNode reverseKGroup(ListNode head, int k) {
    ListNode node = head;
    int count = 0;
    while (node != null && count < k) { node = node.next; count++; }
    if (count < k) return head;              // fewer than k nodes left - leave unchanged

    ListNode newHead = reverseKGroup(node, k); // recursively handle everything after this group first
    ListNode curr = head;
    ListNode prev = newHead;
    for (int i = 0; i < k; i++) {              // reverse exactly this group of k nodes
        ListNode next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;
    }
    return prev;   // the new head of this (now-reversed) group
}

Python

def reverse_k_group(head: ListNode | None, k: int) -> ListNode | None:
    node = head
    count = 0
    while node is not None and count < k:
        node = node.next
        count += 1
    if count < k:
        return head                          # fewer than k nodes left - leave unchanged

    new_head = reverse_k_group(node, k)      # recursively handle everything after this group first
    curr = head
    prev = new_head
    for _ in range(k):                       # reverse exactly this group of k nodes
        nxt = curr.next
        curr.next = prev
        prev = curr
        curr = nxt
    return prev   # the new head of this (now-reversed) group

Counting first is what keeps the short last group simple: it's an early return, not an undo. The recursion handles the rest of the list before this group is reversed. So prev starts out pointing at the already-finished remainder, and the reversal links the group straight into it.

A second flavor: reversing one subrange

Reversing only positions left to right needs a different move. Keep an anchor, prev, on the node just before the range. Keep curr on the range's first node; it will end up as the range's tail, so it never moves. Then, again and again, take the node right after curr and move it to the front of the range, right after the anchor.

Reversing positions 2 to 4 of 4 -> 9 -> 2 -> 7 -> 5 (the anchor is 4, curr is 9):

StepNode moved to the frontList
Start4 -> 9 -> 2 -> 7 -> 5
124 -> 2 -> 9 -> 7 -> 5
274 -> 7 -> 2 -> 9 -> 5

Java

ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
for (int i = 0; i < left - 1; i++) prev = prev.next;   // prev: the anchor, fixed just before the range

ListNode curr = prev.next;   // curr: fixed at the range's ORIGINAL start - it becomes the range's tail
for (int i = 0; i < right - left; i++) {
    ListNode moved = curr.next;      // pull the node right after curr...
    curr.next = moved.next;
    moved.next = prev.next;          // ...and insert it right after the anchor
    prev.next = moved;
}
return dummy.next;

Python

def reverse_between(head: ListNode | None, left: int, right: int) -> ListNode | None:
    dummy = ListNode(0, head)
    prev = dummy
    for _ in range(left - 1):
        prev = prev.next                     # prev: the anchor, fixed just before the range

    curr = prev.next   # curr: fixed at the range's ORIGINAL start - it becomes the range's tail
    for _ in range(right - left):
        moved = curr.next                    # pull the node right after curr...
        curr.next = moved.next
        moved.next = prev.next               # ...and insert it right after the anchor
        prev.next = moved
    return dummy.next

Where you'll see it

Processing a stream in fixed-size batches works the same way: measure a full batch, act on it as a whole, and hold back a partial last batch. A buffer that flushes only full pages does exactly this. The subrange version is like editing one known section of a document in place.

Which tool for which job?

You needUse
Reverse every k nodes, leave a short tailcheck k nodes exist, then reverse that group
The same in O(1) extra spaceiterative, keeping the previous group's tail
Reverse positions left..rightanchor before the range, move each next node to the front
Swap every pairk-group with k = 2
Reverse the short tail toodrop the "full group" check for the last group
Edits that may include the heada dummy node before it

Common mistakes

MistakeWhat happensDo this instead
Reversing before counting k nodesa short tail gets reversedcount first, then reverse
Not linking the previous group to the new headgroups fall off the listgroupPrev.next = kth, then move groupPrev
Advancing curr in subrange reversalthe wrong nodes movecurr stays the range's first node
No dummy when the range starts at 1special case for the headanchor at a dummy
Recursing once per group on long listsstack overflowiterate

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. Why count k nodes before reversing anything?

Show answer

If you reverse first and then find fewer than k nodes, you have to undo the reversal, which is easy to get wrong. Counting first makes "leave a short last group alone" a simple early return.

2. After a group is reversed, why must its old head be linked to the next group?

Show answer

Reversing flips every link inside the group, so the old head is now the tail. Without a link forward, it points at nothing useful, and the groups become separate fragments instead of one list.

3. In subrange reversal, why does curr never move?

Show answer

curr is the range's first node, and it ends up as the range's tail. Each step takes the node right after curr and moves it to the front. That only works if curr stays put. Advance it and you start moving the wrong nodes.

Key takeaways

  • Count k nodes before reversing a group, so a short last group is a simple early return.
  • A reversed group's old head is its new tail. Link it to the next group's new head.
  • To reverse a subrange, keep an anchor before it and keep moving the node after the range's first node to the front.
  • In that loop, the range's first node stays fixed; it becomes the tail.
  • The two techniques look alike but rewire differently. Copying one's loop into the other gives subtly wrong lists.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
k at a timecount, then reverse
O(1) spaceiterative with groupPrev
left..rightanchor + move-to-front
Swap pairsk = 2
Groups from the endskip n % k first

Snippets worth knowing by heart

Java

ListNode dummy = new ListNode(0, head), groupPrev = dummy;
while (true) {
    ListNode kth = groupPrev;
    for (int i = 0; i < k && kth != null; i++) kth = kth.next;
    if (kth == null) break;                         // fewer than k left: keep them
    ListNode groupNext = kth.next, prev = groupNext, curr = groupPrev.next;
    while (curr != groupNext) { ListNode nx = curr.next; curr.next = prev; prev = curr; curr = nx; }
    ListNode oldFirst = groupPrev.next;
    groupPrev.next = kth;                           // stitch to the new head
    groupPrev = oldFirst;                           // the new tail
}
return dummy.next;

Python

dummy = ListNode(0, head)
prev = dummy
for _ in range(left - 1):
    prev = prev.next                 # anchor before the range
curr = prev.next                     # stays put: the reversed part's tail
for _ in range(right - left):
    move = curr.next
    curr.next = move.next
    move.next = prev.next
    prev.next = move                 # move it to the front of the range
return dummy.next

The traps

  • Reversing before counting: a short tail gets reversed. Count k nodes first.
  • Not stitching groups: groups fall off the list. Set groupPrev.next = kth, then move groupPrev.
  • Moving curr in the subrange version: the wrong nodes move. curr stays the range's first node.
  • No dummy for left = 1: the head needs a special case. Anchor at a dummy.
  • Recursion on long lists: one call per group can overflow the stack. Iterate.

Staff-level points, one line each

  • Iterative k-group: O(1) space; 1..11, k = 3 → [3, 2, 1, 6, 5, 4, 9, 8, 7, 10, 11].
  • Reversing the leftover is one condition: [..., 11, 10].
  • Each node visited about twice (19 visits for 10 nodes, k = 3).
  • Recursive on 5,000 nodes, k = 2: RecursionError.
  • Subrange invariant: curr is always the reversed part's tail.

Say it in an interview

  • "I check that k nodes remain before I reverse anything."
  • "After each group, the old first node is the new tail, so it links to the next group."
  • "Iteratively it's O(n) time and O(1) space."
  • "For a subrange I keep moving the next node to the front of the range."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Linked List Group Reversal free

Reverse Linked List II

MediumProCoding problemJava · Python

Reverse just one stretch of a linked list, from position left to position right (counting from 1), and leave the rest as it was. Return the head.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Reverse Nodes in k-Group

HardProCoding problemJava · Python

Walk through a linked list in groups of k nodes and reverse the order inside each full group. A last group with fewer than k nodes stays as it is. Return the new head.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Linked List Group Reversal free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime