class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
dummy = ListNode(0)
dummy.next = head
prev = dummy
while True:
node = prev
# Check if there are k nodes left to reverse
for i in range(k):
node = node.next
if not node:
return dummy.next
# Reverse k nodes
curr = prev.next
nex = curr.next
for i in range(k - 1):
curr.next = nex.next
nex.next = prev.next
prev.next = nex
nex = curr.next
prev = curr
/**
* 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* reverseKGroup(ListNode* head, int k) {
ListNode dummy(0);
dummy.next = head;
ListNode* prev = &dummy;
while (true) {
ListNode* node = prev;
// Check if there are k nodes to reverse
for (int i = 0; i < k && node; ++i) {
node = node->next;
}
if (!node) break;
ListNode* curr = prev->next;
ListNode* nex = curr->next;
for (int i = 1; i < k; ++i) {
curr->next = nex->next;
nex->next = prev->next;
prev->next = nex;
nex = curr->next;
}
prev = curr;
}
return dummy.next;
}
};
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode prev = dummy;
while (true) {
ListNode node = prev;
// Check if there are k nodes to reverse
for (int i = 0; i < k && node != null; ++i) {
node = node.next;
}
if (node == null) break;
ListNode curr = prev.next;
ListNode nex = curr.next;
for (int i = 1; i < k; ++i) {
curr.next = nex.next;
nex.next = prev.next;
prev.next = nex;
nex = curr.next;
}
prev = curr;
}
return dummy.next;
}
}
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var reverseKGroup = function(head, k) {
let dummy = new ListNode(0, head);
let prev = dummy;
while (true) {
let node = prev;
// Check if there are k nodes to reverse
for (let i = 0; i < k && node; ++i) {
node = node.next;
}
if (!node) break;
let curr = prev.next;
let nex = curr.next;
for (let i = 1; i < k; ++i) {
curr.next = nex.next;
nex.next = prev.next;
prev.next = nex;
nex = curr.next;
}
prev = curr;
}
return dummy.next;
};
Given the head of a singly linked list, reverse the nodes of the list k
at a time, and return the modified list. Nodes that are left with less than k
elements at the end should remain in their original order.
k
nodes must be reversed as a unit.k
, leave the last group as is.next
pointers.
At first glance, this problem seems similar to reversing a linked list, but with the added complexity of only reversing every consecutive group of k
nodes. If the list is not a multiple of k
, the last few nodes should remain unchanged.
The brute-force approach would be to collect k
nodes, reverse them, then move to the next group. However, we need to do this in-place without extra space for the nodes themselves. This means careful pointer manipulation is required.
To optimize, we can use a dummy head node to simplify edge cases (like reversing at the head), and always check if there are enough nodes left before attempting to reverse. We need to keep track of the previous group's tail, the current node, and the next node during reversal.
k
nodes left. If not, stop processing.k
nodes. This is done by iteratively moving each node after the head of the group to the front of the group.next
pointers to avoid losing references to the remainder of the list.prev
pointer to the end of the reversed group (which is now the start of the next group).next
pointer of the dummy node, which now points to the new head.This approach allows us to reverse nodes in-place, group by group, while maintaining the correct connections between nodes.
Input: head = [1,2,3,4,5]
, k = 3
3 -> 2 -> 1
k
, so leave them unchanged.
3 -> 2 -> 1 -> 4 -> 5
At each reversal, the code carefully updates the next
pointers so that the groups are reversed in-place, and the rest of the list remains connected properly.
This problem is a classic example of in-place linked list manipulation. By using a dummy node and carefully managing pointers, we can reverse every group of k
nodes efficiently. The key insight is to always check for enough nodes before reversing and to update connections as we go, resulting in a clean and optimal O(n) time, O(1) space solution.