Reverse Nodes in k-Group
You're given the head of a singly linked list and a positive integer k. Starting from the head, split the list into consecutive groups of k nodes and reverse the order of the nodes within each group, then return the new head. If fewer than k nodes remain at the end, leave that last group in its original order. Change the links between nodes, not the values stored in them, and aim for O(1) extra space.
Examples
head = [1,2,3,4,5], k = 2 returns [2,1,4,3,5]
The groups are (1,2), (3,4) and (5). Both full pairs flip to 2,1 and 4,3, while the lone 5 is fewer than k = 2 nodes, so it stays where it is.
head = [1,2,3,4,5], k = 3 returns [3,2,1,4,5]
The first three nodes form a full group and become 3,2,1. Only 4 and 5 remain, fewer than k = 3, so they keep their original order.
Constraints
- 1 <= k <= n <= 5000
Hints
How could you reverse a fixed-length chunk in place and stitch it back into the surrounding list?
Use a dummy node and a groupPrev pointer; per group, peek k ahead and reverse the segment in place.
With dummy.next = head and groupPrev = dummy, repeatedly find the kth node from groupPrev. If it exists, reverse the k-node segment between groupPrev.next and kth, reconnect groupPrev.next to kth and the reversed tail to the original groupNext, then move groupPrev to the new tail. Stop when fewer than k nodes remain.
Drill This: Your Approach First
Approach
Put a dummy node before the head and track groupPrev, the node just before the current group. Step k nodes past groupPrev to find the group's kth node; if the list ends first, stop, which leaves a short final group untouched. Otherwise reverse the group's links starting with prev = kth.next, so the group's old first node ends up pointing at the next group, then set groupPrev.next = kth and move groupPrev to that old first node. O(n) time, O(1) extra space.
Time
O(n)
Space
O(1)
Pitfall
Solutions
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0, head);
ListNode groupPrev = dummy;
while (true) {
ListNode kth = getKth(groupPrev, k);
if (kth == null) break;
ListNode groupNext = kth.next;
ListNode prev = groupNext, curr = groupPrev.next;
while (curr != groupNext) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
ListNode tmp = groupPrev.next;
groupPrev.next = kth;
groupPrev = tmp;
}
return dummy.next;
}
private ListNode getKth(ListNode node, int k) {
while (node != null && k > 0) {
node = node.next;
k--;
}
return node;
}
}class Solution:
def reverseKGroup(self, head, k):
dummy = ListNode(0, head)
group_prev = dummy
def get_kth(node, k):
while node and k > 0:
node = node.next
k -= 1
return node
while True:
kth = get_kth(group_prev, k)
if not kth:
break
group_next = kth.next
prev, curr = group_next, group_prev.next
while curr is not group_next:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
tmp = group_prev.next
group_prev.next = kth
group_prev = tmp
return dummy.next