class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def deleteNodes(head: ListNode, m: int, n: int) -> ListNode:
curr = head
while curr:
# Skip m nodes
for i in range(1, m):
if curr is None:
return head
curr = curr.next
if curr is None:
break
# Delete next n nodes
temp = curr.next
for j in range(n):
if temp is None:
break
temp = temp.next
curr.next = temp
curr = temp
return head
/**
* 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) {}
* };
*/
ListNode* deleteNodes(ListNode* head, int m, int n) {
ListNode* curr = head;
while (curr) {
// Skip m-1 nodes
for (int i = 1; i < m && curr; ++i)
curr = curr->next;
if (!curr)
break;
// Delete next n nodes
ListNode* temp = curr->next;
for (int j = 0; j < n && temp; ++j)
temp = temp->next;
curr->next = temp;
curr = temp;
}
return head;
}
/**
* 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; }
* }
*/
public ListNode deleteNodes(ListNode head, int m, int n) {
ListNode curr = head;
while (curr != null) {
// Skip m-1 nodes
for (int i = 1; i < m && curr != null; i++) {
curr = curr.next;
}
if (curr == null) break;
// Delete next n nodes
ListNode temp = curr.next;
for (int j = 0; j < n && temp != null; j++) {
temp = temp.next;
}
curr.next = temp;
curr = temp;
}
return head;
}
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
var deleteNodes = function(head, m, n) {
let curr = head;
while (curr) {
// Skip m-1 nodes
for (let i = 1; i < m && curr; i++) {
curr = curr.next;
}
if (!curr) break;
// Delete next n nodes
let temp = curr.next;
for (let j = 0; j < n && temp; j++) {
temp = temp.next;
}
curr.next = temp;
curr = temp;
}
return head;
};
Given the head of a singly linked list, and two integers m
and n
, the task is to modify the list such that after keeping the first m
nodes, you delete the next n
nodes. You repeat this process until you reach the end of the list.
The function should return the head of the modified linked list. You must not create new nodes or reuse deleted nodes; you should only change the next
pointers to achieve the result.
To solve this problem, we need to traverse the linked list and alternate between keeping and deleting nodes. At first glance, one might consider copying the values into a new list, but this would violate the constraint of not creating or reusing nodes. Instead, we must manipulate the existing next
pointers.
The brute-force approach would be to traverse the list, count nodes, and delete as needed, but this can be error-prone if not carefully managed. To optimize, we can use two pointers: one to skip the nodes to keep, and another to skip and remove the nodes to delete. This way, we ensure we only traverse each part of the list once.
The key insight is to carefully manage the pointers so that after skipping m
nodes, we can link the last kept node directly to the node after the n
nodes to be deleted.
m-1
times (to keep m
nodes). If you reach the end, stop.n
times to skip the nodes to be deleted. Again, if you reach the end, stop.next
pointer to the node after the last deleted node (or null
if at the end).We use a single traversal, only updating pointers as needed, which is efficient and adheres to the problem's constraints.
Suppose the input linked list is 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10
, and m = 2
, n = 3
.
1 -> 2 -> 6 -> 7 -> 8 -> 9 -> 10
.1 -> 2 -> 6 -> 7
.
The final linked list is 1 -> 2 -> 6 -> 7
.
The optimized approach is both time and space efficient because it works in-place and only requires a single pass through the list.
By carefully managing the traversal and pointer updates, we can efficiently delete every group of n
nodes after every group of m
nodes in a singly linked list. The key insight is to avoid unnecessary data structures and simply manipulate the next
pointers as we traverse. This leads to an elegant, in-place, and optimal solution.