💡 Approach
The idea is to reverse each group of k
nodes while maintaining the correct links to the rest of the list.
Here’s the plan:
- Use a dummy node before the head to simplify edge case handling.
- For each group of
k
nodes:- Use a helper
getKth
function to find thek
-th node from the current position. - If fewer than
k
nodes are left, break the loop. - Reverse the
k
nodes using standard in-place reversal logic. - Connect the reversed group with the previous and next parts of the list.
- Use a helper
This is a constant space, in-place reversal of linked list nodes.
🔁 Step-by-step
Dummy Node:
A dummy node is created and linked to head to handle edge cases where head itself changes.Find k-th node:
Use a helper functiongetKth
to find the end of the current group. If less thank
nodes are left, returnnull
.Reverse nodes in the group:
Usingcurr
,prev
, and atmp
pointer, reverse the links inside the current group.Reconnect the group:
After reversal, connect the previous group to the newly reversed group. UpdategroupPrev
to point to the end of this group.Repeat until no more groups.
🧮 Time Complexity
Time Complexity: O(N)
Each node is visited and reversed exactly once.Space Complexity: O(1)
No extra space except for a few pointers.
Diagrams
🧑💻 JavaScript Code
// Definition for singly-linked list node
function ListNode(val, next) {
this.val = (val === undefined ? 0 : val);
this.next = (next === undefined ? null : next);
}
/**
* Reverse nodes of a linked list in groups of size k
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var reverseKGroup = function (head, k) {
let dummy = new ListNode(0, head);
let groupPrev = dummy;
while (true) {
let kth = getKth(groupPrev, k);
if (kth == null) break;
let groupNext = kth.next;
let curr = groupPrev.next;
let prev = groupNext;
// Reverse the group
while (curr !== groupNext) {
let tmp = curr.next;
curr.next = prev;
prev = curr;
curr = tmp;
}
let tmp = groupPrev.next;
groupPrev.next = kth;
groupPrev = tmp;
}
return dummy.next;
};
/**
* Helper to get the k-th node from the current node
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
const getKth = (head, k) => {
let curr = head;
while (curr && k > 0) {
curr = curr.next;
k--;
}
return curr;
};
✅ Example
For list: 1 -> 2 -> 3 -> 4 -> 5
, and k = 2
, the output will be:
2 -> 1 -> 4 -> 3 -> 5
For k = 3
:
3 -> 2 -> 1 -> 4 -> 5
🔚 Conclusion
This problem is a beautiful blend of pointer manipulation and clean logic. Mastering problems like these sharpens your understanding of linked lists and in-place algorithms.