Linked List
1. Reverse Nodes in k-Group
HardGiven 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 that is at most the length of the list. If the number of nodes is not a multiple of k, the left-out nodes at the end stay in their original order. Only the nodes' links may be changed, not their values.
Use a dummy node in front of the list so the first group can be handled like every other group, and keep a pointer group_prev to the node just before the current group. For each group:
1. Find the group. Walk k steps from group_prev with getKth to get kth, the last node of the group. If it returns None, fewer than k nodes are left, so stop. Otherwise group_next = kth.next is the first node of the next group.
2. Reverse the group. Reverse the links as in a normal linked-list reversal, but start prev at group_next instead of None. The old first node then points to the next group automatically.
3. Reconnect. The old first node is now the tail of the reversed group. Save it in tmp, point group_prev.next at kth (the new head of the group), then move group_prev to tmp and repeat.
Every node is visited a constant number of times (once to find the group, once to reverse it), so the total time is \(O(N)\) with only a few pointers of extra space.
Input: 1 → 2 → 3 → 4 → 5 Output: 2 → 1 → 4 → 3 → 5
① Find the group
kth = getKth(group_prev, k); group_next = kth.nextWalk k steps from group_prev to reach kth. The node after it, group_next, starts the next group.
② Reverse the group (inner while loop)
prev, curr = group_next, group_prev.next → tmp = curr.next; curr.next = prev; prev = curr; curr = tmp1.next = group_next (3) (green arc) and 2.next = 1. The dummy still points to 1 (grey, old link) until we reconnect.
③ Reconnect and move group_prev
tmp = group_prev.next; group_prev.next = kth; group_prev = tmpD.next = kth (2). The old first node 1 is now the group's tail, so it becomes the new group_prev.
④ Second group: repeat with the new group_prev
kth = getKth(group_prev, k) → 4; group_next = kth.next → 5Same three moves again on nodes 3 and 4: reverse them so 3 → 5 and 4 → 3, then set group_prev.next = kth (1 → 4).
⑤ Reverse 3, 4 → reconnect → stop
getKth(group_prev, k) returns None (only node 5 left) → break; return dummy.nextOnly node 5 is left, fewer than k, so getKth returns None and the loop breaks. Result: 2 → 1 → 4 → 3 → 5.
def reverseKGroup(head: Optional[ListNode], k: int) -> Optional[ListNode]:
def getKth(curr, k):
while curr and k > 0:
curr = curr.next
k -= 1
return curr
dummy = ListNode(0, head)
group_prev = dummy
while True:
kth = getKth(group_prev, k)
if not kth:
break
group_next = kth.next
# Reverse the group; prev starts at group_next to link the tail
prev, curr = group_next, group_prev.next
while curr != group_next:
tmp = curr.next
curr.next = prev
prev = curr
curr = tmp
# Reconnect: old first node is now the group's tail
tmp = group_prev.next
group_prev.next = kth
group_prev = tmp
return dummy.next
