🧠
Iterative Approach with Helper Function for Reversal
💡 This approach modularizes the reversal logic into a helper function to improve code clarity and reuse, while still performing in-place iterative reversal.
Intuition
Separate the reversal of k nodes into a helper function, then use a loop to process the entire list group by group.
Algorithm
- Create a dummy node pointing to head.
- Iterate through the list, checking if k nodes remain.
- Call a helper function to reverse k nodes and return new head and tail.
- Connect reversed group to previous part and continue until fewer than k nodes remain.
💡 Breaking down reversal into a helper function makes the main logic easier to follow but requires careful pointer management.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reverseLinkedList(head, k):
prev = None
curr = head
while k > 0:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
k -= 1
return prev
def reverseKGroup(head, k):
dummy = ListNode(0)
dummy.next = head
group_prev = dummy
while True:
kth = group_prev
count = 0
while kth.next and count < k:
kth = kth.next
count += 1
if count < k:
break
group_next = kth.next
# Reverse k nodes
prev = reverseLinkedList(group_prev.next, k)
tail = group_prev.next
tail.next = group_next
group_prev.next = prev
group_prev = tail
return dummy.next
# Driver code
if __name__ == '__main__':
nodes = [ListNode(i) for i in range(1, 6)]
for i in range(4):
nodes[i].next = nodes[i+1]
new_head = reverseKGroup(nodes[0], 2)
curr = new_head
while curr:
print(curr.val, end=' ')
curr = curr.next
Line Notes
def reverseLinkedList(head, k):Helper function to reverse exactly k nodes
while kth.next and count < k:Check if k nodes exist before reversal
prev = reverseLinkedList(group_prev.next, k)Reverse k nodes using helper
group_prev.next = prevConnect previous group's tail to reversed head
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
}
public class Solution {
private ListNode reverseLinkedList(ListNode head, int k) {
ListNode prev = null;
ListNode curr = head;
while (k > 0) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
k--;
}
return prev;
}
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode groupPrev = dummy;
while (true) {
ListNode kth = groupPrev;
int count = 0;
while (kth.next != null && count < k) {
kth = kth.next;
count++;
}
if (count < k) break;
ListNode groupNext = kth.next;
ListNode prev = reverseLinkedList(groupPrev.next, k);
ListNode tail = groupPrev.next;
tail.next = groupNext;
groupPrev.next = prev;
groupPrev = tail;
}
return dummy.next;
}
public static void main(String[] args) {
ListNode[] nodes = new ListNode[5];
for (int i = 0; i < 5; i++) nodes[i] = new ListNode(i + 1);
for (int i = 0; i < 4; i++) nodes[i].next = nodes[i + 1];
Solution sol = new Solution();
ListNode newHead = sol.reverseKGroup(nodes[0], 2);
ListNode curr = newHead;
while (curr != null) {
System.out.print(curr.val + " ");
curr = curr.next;
}
}
}
Line Notes
private ListNode reverseLinkedList(ListNode head, int k)Helper method to reverse k nodes
while (kth.next != null && count < k)Check if k nodes exist before reversal
ListNode prev = reverseLinkedList(groupPrev.next, k);Reverse k nodes using helper
groupPrev.next = prev;Connect previous group's tail to reversed head
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
ListNode* reverseLinkedList(ListNode* head, int k) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (k > 0) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
k--;
}
return prev;
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode dummy(0);
dummy.next = head;
ListNode* groupPrev = &dummy;
while (true) {
ListNode* kth = groupPrev;
int count = 0;
while (kth->next && count < k) {
kth = kth->next;
count++;
}
if (count < k) break;
ListNode* groupNext = kth->next;
ListNode* prev = reverseLinkedList(groupPrev->next, k);
ListNode* tail = groupPrev->next;
tail->next = groupNext;
groupPrev->next = prev;
groupPrev = tail;
}
return dummy.next;
}
};
int main() {
ListNode* nodes[5];
for (int i = 0; i < 5; i++) nodes[i] = new ListNode(i + 1);
for (int i = 0; i < 4; i++) nodes[i]->next = nodes[i + 1];
Solution sol;
ListNode* newHead = sol.reverseKGroup(nodes[0], 2);
ListNode* curr = newHead;
while (curr) {
cout << curr->val << " ";
curr = curr->next;
}
cout << endl;
return 0;
}
Line Notes
ListNode* reverseLinkedList(ListNode* head, int k)Helper function to reverse k nodes
while (kth->next && count < k)Check if k nodes exist before reversal
ListNode* prev = reverseLinkedList(groupPrev->next, k);Reverse k nodes using helper
groupPrev->next = prev;Connect previous group's tail to reversed head
function ListNode(val, next = null) {
this.val = val;
this.next = next;
}
function reverseLinkedList(head, k) {
let prev = null;
let curr = head;
while (k > 0) {
let next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
k--;
}
return prev;
}
function reverseKGroup(head, k) {
const dummy = new ListNode(0);
dummy.next = head;
let groupPrev = dummy;
while (true) {
let kth = groupPrev;
let count = 0;
while (kth.next !== null && count < k) {
kth = kth.next;
count++;
}
if (count < k) break;
const groupNext = kth.next;
const prev = reverseLinkedList(groupPrev.next, k);
const tail = groupPrev.next;
tail.next = groupNext;
groupPrev.next = prev;
groupPrev = tail;
}
return dummy.next;
}
// Driver code
const nodes = [1,2,3,4,5].map(v => new ListNode(v));
for (let i = 0; i < nodes.length - 1; i++) nodes[i].next = nodes[i+1];
const newHead = reverseKGroup(nodes[0], 2);
let curr = newHead;
while (curr) {
console.log(curr.val);
curr = curr.next;
}
Line Notes
function reverseLinkedList(head, k)Helper function to reverse k nodes
while (kth.next !== null && count < k)Check if k nodes exist before reversal
const prev = reverseLinkedList(groupPrev.next, k);Reverse k nodes using helper
groupPrev.next = prev;Connect previous group's tail to reversed head
Each node is visited once and reversed in-place using the helper function, so time is linear and space is constant.
💡 This approach is as efficient as the previous iterative one but improves code readability.
Interview Verdict: Accepted and optimal with modular code
This approach is ideal for interviews where clean, modular code is valued alongside efficiency.