ExerciseDifficulty: Advanced2 min

Practice: Reversing Boarding Groups Three at a Time

Passengers queue in a linked list: reverse every group of three, and leave a final group of fewer than three as it is.

Reversing a list in groups combines the four reversal lines with counting ahead and a dummy node. Passengers A B C D E F G H queue for boarding as a linked list, and the gate boards each group of three in reverse order. Reverse every group of three in place, leave a final group of fewer than three as it is, and say what the queue becomes. Use O(1) extra memory.

Show the answer and a solution

The queue becomes C B A F E D G H. Start from a dummy node before A, with before on the dummy. For each group, count three nodes ahead from before; if the count runs out, the rest is a short group and stays. Otherwise reverse the three with the four lines, starting prev at the node after the group so the group's new last node links straight on, then point before.next at the group's new first node and move before to its new last node. The steps follow each group.

text
--- group 1
counted: A B C
list: dummy → C → B → A → D → E → F → G → H → null
before: A
--- group 2
counted: D E F
list: dummy → C → B → A → F → E → D → G → H → null
before: D
--- group 3
counted: G H, fewer than 3
list: dummy → C → B → A → F → E → D → G → H → null
left as it is

The listing runs the whole queue.

reverse_groups.pypy
class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None


def build(values):
    head = None
    for val in reversed(values):
        node = ListNode(val)
        node.next = head
        head = node
    return head


def values_of(head):
    values = []
    while head:
        values.append(head.val)
        head = head.next
    return values


def reverse_in_groups(head, k):
    dummy = ListNode("dummy")
    dummy.next = head
    before = dummy
    while True:
        end = before
        for _ in range(k):
            end = end.next
            if end is None:
                return dummy.next
        first, after = before.next, end.next
        prev, curr = after, first
        while curr is not after:
            next_node = curr.next
            curr.next = prev
            prev = curr
            curr = next_node
        before.next = end
        before = first


print("groups of 3:", *values_of(reverse_in_groups(build(list("ABCDEFGH")), 3)))
OutputRan with python:3.14.8-slim-trixie (Python 3.14.8)
groups of 3: C B A F E D G H

Each node is counted once and reversed at most once, so the solution is O(n) time for n passengers and O(1) extra space. Counting before reversing is what leaves G H alone: a version that reverses first and checks after would turn the short group round.