Reverse a Linked List in Groups of K
Solve this Problemk, reverse every consecutive group of k nodes. If the number of nodes remaining at the end isn't a full group of k, leave that final partial group exactly as it is.
The optimal solution never reverses a group speculatively — it always peeks k nodes ahead with a throwaway check pointer first, confirming a full group exists before touching a single .nextLook Before You LeapReversing pointers is easy to do but hard to undo cleanly mid-way. Confirming the precondition (a full group of k nodes) BEFORE any relinking starts means the algorithm never has to detect a failure partway through and unwind it — by the time reversal begins, success is already guaranteed. pointer. Once confirmed, each group is reversed with the same three-pointer dance used to reverse an entire list, and a trailing groupPrev — anchored at the previous group's original first node, now its tail — links each freshly-reversed group to the next.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ number of nodes in head ≤ 200 - ◆
-1000 ≤ node value ≤ 1000 - ◆
1 ≤ k ≤ number of nodes in head
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public Node reverseKGroup(Node head, int k) { |
| 3 | Node dummy = new Node(0); |
| 4 | dummy.next = head; |
| 5 | Node groupPrev = dummy; |
| 6 | while (true) { |
| 7 | Node check = groupPrev; |
| 8 | for (int i = 0; i < k; i++) { |
| 9 | check = check.next; |
| 10 | if (check == null) { |
| 11 | return dummy.next; |
| 12 | } |
| 13 | } |
| 14 | Node prev = check.next; |
| 15 | Node curr = groupPrev.next; |
| 16 | for (int i = 0; i < k; i++) { |
| 17 | Node nextNode = curr.next; |
| 18 | curr.next = prev; |
| 19 | prev = curr; |
| 20 | curr = nextNode; |
| 21 | } |
| 22 | Node groupStart = groupPrev.next; |
| 23 | groupPrev.next = prev; |
| 24 | groupPrev = groupStart; |
| 25 | } |
| 26 | } |
| 27 | } |
| 28 |
dummyA dummy node lets the very first group reverse the same way as every later one. groupPrev starts at dummy.
Approach & Solutions
Brute Force — Collect Values, Reverse Each Full Chunk, Write Back
GoodCopy every value into an array, then walk it in chunks of k, reversing each chunk that has a full k elements (a trailing shorter chunk is left untouched) with a two-pointer swap — the same swap used to reverse a single sublist, just applied once per chunk. Walk the list once more overwriting .val in that transformed order. Correct, but it costs an array the size of the whole list and two full passes — the optimal solution reverses each group in place, in a single pass.
O(n)O(n)1// Node definition used in this problem:
2// class Node {
3// int val;
4// Node next;
5// }
6
7class Solution {
8 public Node reverseKGroup(Node head, int k) {
9 List<Integer> vals = new ArrayList<>();
10 Node curr = head;
11 while (curr != null) {
12 vals.add(curr.val);
13 curr = curr.next;
14 }
15 int i = 0;
16 while (i + k <= vals.size()) {
17 int lo = i, hi = i + k - 1;
18 while (lo < hi) {
19 int temp = vals.get(lo);
20 vals.set(lo, vals.get(hi));
21 vals.set(hi, temp);
22 lo++;
23 hi--;
24 }
25 i += k;
26 }
27 curr = head;
28 for (int v : vals) {
29 curr.val = v;
30 curr = curr.next;
31 }
32 return head;
33 }
34}Optimal — Iterative In-Place Group Reversal With a Trailing groupPrev
OptimalA dummy node lets the first group reverse the same way as every later one, with groupPrev anchored right before each group. Before touching anything, peek k nodes ahead with a throwaway check pointer — if fewer than k nodes remain, stop immediately and leave them exactly as they are (reversing first and discovering there weren't enough nodes would be far harder to undo). Once a full group is confirmed, reverse it with the same three-pointer dance used to reverse an entire list, then move groupPrev up to the group's original first node — now its tail — ready to anchor the next group.
O(n)O(1)1// Node definition used in this problem:
2// class Node {
3// int val;
4// Node next;
5// }
6
7class Solution {
8 public Node reverseKGroup(Node head, int k) {
9 Node dummy = new Node(0);
10 dummy.next = head;
11 Node groupPrev = dummy;
12 while (true) {
13 Node check = groupPrev;
14 for (int i = 0; i < k; i++) {
15 check = check.next;
16 if (check == null) {
17 return dummy.next;
18 }
19 }
20 Node prev = check.next;
21 Node curr = groupPrev.next;
22 for (int i = 0; i < k; i++) {
23 Node nextNode = curr.next;
24 curr.next = prev;
25 prev = curr;
26 curr = nextNode;
27 }
28 Node groupStart = groupPrev.next;
29 groupPrev.next = prev;
30 groupPrev = groupStart;
31 }
32 }
33}