Skip to content
DSAPrep

    ↑↓ to move · Enter to open · Esc to close

    Reverse Nodes in K Group

    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 nodes is not a multiple of k then the left-out nodes at the end should remain as they are.

    You may not alter the values in the list's nodes — only the nodes themselves may be rearranged.

    Example 1

    Input: head = [1,2,3,4,5], k = 2

    Output: [2,1,4,3,5]

    Example 2

    Input: head = [1,2,3,4,5], k = 3

    Output: [3,2,1,4,5]

    Constraints

    • The number of nodes in the list is n.
    • 1 <= k <= n <= 5000
    • 0 <= Node.val <= 1000
    Follow-up: Can you solve the problem in O(1) extra memory space?
    View original on LeetCode ↗

    This extends the classic “reverse a linked list” pointer-flipping technique, applied one group of k nodes at a time instead of to the whole list. The extra bookkeeping is stitching each reversed group back onto the node that came before it — and correctly leaving a final short group (fewer than k nodes) untouched.

    Recursive

    Time O(n)Space O(n/k)

    First check whether at least k nodes remain from the current position — if not, this is a trailing partial group, so return it unreversed. Otherwise, reverse exactly k nodes using the standard iterative reversal, then recursively solve the rest of the list and attach it after the original head (which is now the tail of this reversed group).

    class ListNode:
    def __init__(self, val=0, next=None):
    self.val = val
    self.next = next
    class Solution:
    def reverseKGroup(self, head: ListNode | None, k: int) -> ListNode | None:
    node = head
    count = 0
    while node and count < k:
    node = node.next
    count += 1
    if count < k:
    return head # fewer than k nodes left: leave them as-is
    prev, curr = None, head
    for _ in range(k):
    next_node = curr.next
    curr.next = prev
    prev = curr
    curr = next_node
    head.next = self.reverseKGroup(curr, k) # head is now the tail of this group
    return prev

    Clean and mirrors the group structure directly, but the recursion creates one stack frame per group, so the call stack grows to O(n/k) frames — the iterative version below avoids that to satisfy the O(1) follow-up.

    Iterative

    OptimalTime O(n)Space O(1)

    Use a dummy node before head and a group_prev pointer that always sits just before the group currently being reversed. For each group: first scan ahead k nodes to confirm a full group exists (returning early if not), then reverse that group in place using the same three-pointer technique, and finally reconnect group_prev to the new head of the reversed group before advancing group_prev to what is now the group’s tail.

    class Solution:
    def reverseKGroup(self, head: ListNode | None, k: int) -> ListNode | None:
    dummy = ListNode(0, head)
    group_prev = dummy
    while True:
    kth = group_prev
    for _ in range(k):
    kth = kth.next
    if not kth:
    return dummy.next # fewer than k nodes left: done
    group_next = kth.next # first node after this group
    prev, curr = group_next, group_prev.next
    while curr != group_next:
    next_node = curr.next
    curr.next = prev
    prev = curr
    curr = next_node
    tmp = group_prev.next # this group's original head, now its tail
    group_prev.next = kth # kth is now this group's head
    group_prev = tmp

    Watch the three pointers inside one group: prev starts at group_next, the node after the group, so every flipped next eventually chains the group tail to the rest of the list.

    k = 2scan lookahead
    group_prevDkthnullgroup_next—prev—curr—next—
    D
    1
    2
    3
    4
    5
    ▲ group_prev
    1 / 12
    currentresultseen

    dummy sits before head and group_prev starts at dummy, so the first group is the first k nodes.

    Why it’s correct: each full group is reversed with the same proven-correct in-place reversal, and group_prev always points to the node immediately before the next group to process — so reconnecting group_prev.next to the reversed group’s new head preserves the chain between groups. The upfront k-node lookahead guarantees a trailing partial group is detected and left untouched, exactly matching the problem’s requirement. Complexity: each node is visited a constant number of times — once during the lookahead scan and once during reversal — across all groups → O(n) time. Only a fixed number of pointer variables are used, with no recursion or auxiliary data structure → O(1) extra space — this satisfies the follow-up and is optimal, since every node’s next pointer must be touched at least once to reverse it.

    More Linked List practice