Iterative Block Reversal with Tail Reconnection (O(n) Time | O(1) Space)
| LeetCode #25 | Difficulty: Hard |
Intuition
The problem asks us to reverse nodes in groups of size k.
Instead of reversing the entire list at once, we can think in terms of independent blocks of size k:
- If a block has exactly
knodes β reverse it. - If fewer than
knodes remain β leave them as it is.
So the problem reduces to repeating three operations:
- Check if
knodes exist. - Reverse exactly
knodes. - Reconnect the reversed block with the previous and next parts.
The key challenge is handling pointer connections correctly between groups.
Approach
- Maintain:
headβ start of current group.curβ used to check if k nodes exist.newHeadβ head of final modified list.kTailβ tail of previously reversed group.
- For each group:
- Move
curforwardksteps to check ifknodes are available. - If count == k:
- Reverse the
knodes using helperreverseLL. - If this is the first reversed group, update
newHead. - Connect previous groupβs tail (
kTail) to the reversed head. - Update
kTailto current groupβs original head (which becomes tail after reversal). - Move
headforward to the next group start.
- Reverse the
- Move
- If fewer than
knodes remain:- Attach remaining nodes as-is.
- Return:
newHeadif at least one reversal happened.- Otherwise original
head.
Helper Function
reverseLL(head, k):
- Iteratively reverses exactly
knodes. - Uses standard 3-pointer technique.
- Returns new head of reversed block.
Complexity
-
Time complexity: O(n)
Each node is visited a constant number of times. Every node participates in exactly one reversal.
-
Space complexity: O(1)
Only a few pointer variables are used. No recursion or extra data structures.
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseLL(ListNode* head, int k) {
ListNode* cur = head;
ListNode* pre = nullptr;
while(k>0) {
ListNode* temp = cur;
cur = cur->next;
temp->next = pre;
pre = temp;
k--;
}
return pre;
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* cur = head;
ListNode* newHead = nullptr;
ListNode* kTail = nullptr;
while(cur) {
int count = 0;
cur = head;
while(count<k && cur) {
cur = cur->next;
count++;
}
if(count==k) {
ListNode* revHead = reverseLL(head, k);
if(newHead == nullptr) newHead = revHead;
if(kTail!=nullptr) kTail->next = revHead;
kTail = head;
head = cur;
}
}
if(kTail!=nullptr) kTail->next = head;
return (newHead==nullptr) ? head : newHead;
}
};