Definition
Iterate the list group by group. For each full group of k nodes, reverse those k nodes with the three-pointer technique and re-stitch the reversed group between the tail of the previous group and the head of the next group. Stop reversing when fewer than k nodes remain.
The National Bank of India batches settlement slips into fixed bundles of k. Each bundle must be read in reverse, but the bundles stay in their overall order. The clerk flips each bundle of k slips in place, keeping the bundles themselves in sequence, and leaves a final short bundle untouched.
Understanding the Concepts
What is the problem?
Reverse every K-element Sub-list (Reverse Nodes in Groups of K). Given the head of a singly linked list and a positive integer k, reverse every consecutive group of k nodes in place and return the new head. If the final group has fewer than k nodes, leave it as is. Use O(1) extra space.
How does the approach work?
Keep a previousTail pointer that starts at a dummy before the head and, after each reversed group, points to that group's new tail (its original first node). For each group, first confirm k nodes remain by walking ahead; if not, stop. Reverse exactly k nodes with the three-pointer loop, then re-stitch: previousTail.next points to the reversed group's new head (previous), the group's original first node's next points to the next group's first node (current), and previousTail moves to that original first node for the next round.
For example with 1 -> 2 -> 3 -> 4 -> 5 and k=2, the result is 2 -> 1 -> 4 -> 3 -> 5, where the final single node 5 stays put. The count-ahead check is what cleanly leaves a short tail group unreversed.
A senior-level nuance is that this is LeetCode's "Reverse Nodes in k-Group," a hard problem whose difficulty is entirely in the bookkeeping of group boundaries, not the reversal. Doing it with O(1) space means tracking previousTail across groups rather than recursing; the recursive form is cleaner to read but uses O(n/k) stack frames, which the iterative form avoids.
What is the banking use case?
The code contains a BundleNode, a SettlementBundler with reverseInGroups(head, k), and a demo.
How do you implement this in Java?
// ─── File: src/main/java/com/bank/bundle/BundleNode.java ───
package com.bank.bundle;
public class BundleNode {
final int slip;
BundleNode next;
BundleNode(int slip) { this.slip = slip; }
}
// ─── File: src/main/java/com/bank/bundle/SettlementBundler.java ───
package com.bank.bundle;
public class SettlementBundler {
public BundleNode reverseInGroups(BundleNode head, int k) {
if (head == null || k < 2) return head;
BundleNode dummy = new BundleNode(-1);
dummy.next = head;
BundleNode previousTail = dummy;
while (true) {
// Check k nodes remain starting after previousTail.
BundleNode check = previousTail;
for (int i = 0; i < k && check != null; i++) check = check.next;
if (check == null) break; // fewer than k → leave as is
BundleNode groupFirst = previousTail.next; // becomes group tail
BundleNode previous = null, current = groupFirst;
for (int i = 0; i < k; i++) { // reverse k nodes
BundleNode next = current.next;
current.next = previous;
previous = current;
current = next;
}
previousTail.next = previous; // prev group → new group head
groupFirst.next = current; // group tail → next group start
previousTail = groupFirst; // advance for next group
}
return dummy.next;
}
}
// ─── File: src/main/java/com/bank/bundle/GroupDemo.java ───
package com.bank.bundle;
import java.util.logging.Logger;
public class GroupDemo {
private static final Logger log = Logger.getLogger(GroupDemo.class.getName());
public static void main(String[] args) {
BundleNode head = build(new int[]{1, 2, 3, 4, 5});
log.info("Original slips: " + render(head));
BundleNode out = new SettlementBundler().reverseInGroups(head, 2);
log.info("Reversed in groups of 2: " + render(out));
}
static BundleNode build(int[] ids) {
BundleNode d = new BundleNode(-1), t = d;
for (int id : ids) { t.next = new BundleNode(id); t = t.next; }
return d.next;
}
static String render(BundleNode n) {
StringBuilder sb = new StringBuilder();
while (n != null) { sb.append(n.slip);
if (n.next != null) sb.append(" -> "); n = n.next; }
return sb.append(" -> null").toString();
}
}
What is the project structure?
settlement-bundler/
├── pom.xml
└── src/main/java/com/bank/bundle/
├── GroupDemo.java
├── BundleNode.java
└── SettlementBundler.java
How do you build and run?
# Build
mvn clean package -DskipTests
# Run
java -cp target/classes com.bank.bundle.GroupDemo
What is the step-by-step walkthrough?
Input data: chain 1 -> 2 -> 3 -> 4 -> 5, k=2.
previousTail is the dummy. The check walks 2 nodes ahead and finds them present. groupFirst is node 1. Reversing nodes 1 and 2 gives 2 -> 1, with current ending on node 3. Re-stitch: dummy.next becomes node 2, node 1's next becomes node 3, previousTail becomes node 1.groupFirst is node 3. Reversing gives 4 -> 3, with current ending on node 5. Re-stitch: node 1's next becomes node 4, node 3's next becomes node 5, previousTail becomes node 3.2 -> 1 -> 4 -> 3 -> 5.Final output:
2026-10-27 19:25:42 [INFO] Original slips: 1 -> 2 -> 3 -> 4 -> 5 -> null
2026-10-27 19:25:42 [INFO] Reversed in groups of 2: 2 -> 1 -> 4 -> 3 -> 5 -> null
What is the high-level design?
═══ HLD — Batch Slip Bundling ═══
┌──────────┐ batch ┌────────────────────┐ print ┌──────────────┐
│ Scheduler│──────→│ Bundler Svc ×3 │──────→│ Printer Queue│
└──────────┘ │ reverseInGroups(k) │ └──────────────┘
└────────────────────┘
What is the low-level design?
═══ LLD — SettlementBundler ═══
┌─ State across groups ───────────────────────────────┐
│ previousTail → tail of last reversed group │
│ count-ahead check → leaves partial tail untouched │
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ SettlementBundler │
│ + reverseInGroups(head,k): BundleNode │ O(n), O(1)
└──────────────────────────────────────────┘
Contract for reverseInGroups(head,k):
Pre: k ≥ 2
Post: each full k-group reversed; final partial group intact
What is the time and space complexity?
Analyze the solution based on the algorithm used. Consider both the time to process input and the space required for any data structures.
What are common mistakes?
Common mistakes include off-by-one errors, not handling edge cases like empty input, and not considering the constraints of the problem.
What are the edge cases?
Edge cases include empty input, single element input, all identical elements, and boundary values.
What should a senior engineer know?
A senior engineer should understand the time-space tradeoffs, be able to explain the algorithm clearly, and know when this technique applies versus alternatives.
Visual Overview
Input: 1 -> 2 -> 3 -> 4 -> 5 (k=2)
│
▼
SettlementBundler.reverseInGroups()
│ group[1,2] → 2 -> 1 ; previousTail=node1
│ group[3,4] → 4 -> 3 ; previousTail=node3
│ remaining [5] < k → leave
▼
Output: 2 -> 1 -> 4 -> 3 -> 5
Key Takeaway
Reversing a linked list in groups of k is the three-pointer reversal applied repeatedly, and the whole difficulty is the bookkeeping that stitches the groups together rather than the reversal itself. I keep a previous-tail pointer, starting at a dummy before the head, which after each reversed group points to that group's new tail, namely the group's original first node. For each group I first count ahead to confirm k nodes remain; if fewer remain I stop and leave that short tail group in its natural order.
When a full group exists I reverse exactly k nodes with the usual three pointers, then reconnect three links: the previous tail points to the group's new head, the group's original first node points to the start of the next group, and I advance the previous tail to that original first node for the next round. All of this is one forward pass in constant space, and I prefer it over the recursive form because recursion would consume stack proportional to the number of groups.
In my work at the National Bank of India this backed a batch slip printer that printed settlement slips in fixed bundles of k, each bundle reversed internally while the bundles stayed in sequence, with a final short bundle printed normally. Flipping each full bundle in place and carefully relinking the bundle boundaries produced exactly that ordering without building a second chain.
Remember one sentence: understand the core algorithm and apply it to banking domain problems.
---