
Problem Statement
In this problem, you are provided with the head of a singly linked list and two integers, m and n. Your task is to modify the linked list in such a way that, starting from the head, you retain the first m nodes and then delete the next n nodes. This process of keeping m nodes followed by removing n nodes continues repeatedly through the list until no more nodes can be processed. The output should be the head of the linked list after all modifications are performed according to the specified pattern of retention and deletion.
Examples
Example 1
Input:
head = [1,2,3,4,5,6,7,8,9,10,11,12,13], m = 2, n = 3
Output:
[1,2,6,7,11,12]
Explanation:
Keep the first (m = 2) nodes starting from the head of the linked List (1 ->2) show in black nodes. Delete the next (n = 3) nodes (3 -> 4 -> 5) show in read nodes. Continue with the same procedure until reaching the tail of the Linked List. Head of the linked list after removing nodes is returned.
Example 2
Input:
head = [1,2,3,4,5,6,7,8,9,10,11], m = 1, n = 3
Output:
[1,5,9]
Explanation:
Head of linked list after removing nodes is returned.
Constraints
- The number of nodes in the list is in the range
[1, 104]. 1 <= Node.val <= 1061 <= m, n <= 1000
Approach and Intuition
When approaching this problem, the key is to handle the linked list traversal and modification efficiently while keeping track of the nodes. Here’s the step-by-step approach:
- Initialize a pointer, say
current, to point to the head of the linked list. - Traverse the
mnodes starting from thecurrentnode. This is to ensure thesemnodes are retained.- For each of the
mnodes, check if thecurrentpointer is null which indicates the end of the list. If not, simply move thecurrentpointer to the next node.
- For each of the
- Once
mnodes are retained, move to deleting the nextnnodes. This necessitates careful manipulation of the list pointers.- Keep another pointer, let’s call it
prev, which should always point to the last node that is not deleted (last ofmretained nodes). - Now increment the
currentpointer through the nextnnodes. For each node, ensure you adjust the link fromprevto skip the node currently pointed to bycurrent.
- Keep another pointer, let’s call it
- Continue the above two steps until you have traversed the entire list or until the
currentpointer is null. - Return the modified linked list starting from the head.
The intuition here is to effectively manage the pointers as you traverse the list so that you can skip over the n nodes without losing the reference to the part of the list you need to retain. Also, it’s crucial to maintain an efficient approach to not revisit nodes unnecessarily which would otherwise increase the time complexity.
Solutions
- C++
- Java
class Solution {
public:
ListNode* removeNodes(ListNode* head, int m, int n) {
ListNode* current = head;
ListNode* previousMNode = head;
while (current != nullptr) {
int keepCount = m, deleteCount = n;
while (current != nullptr && keepCount != 0) {
previousMNode = current;
current = current->next;
keepCount--;
}
while (current != nullptr && deleteCount != 0) {
current = current->next;
deleteCount--;
}
previousMNode->next = current;
}
return head;
}
};
This solution implements functionality to modify a linked list by preserving 'm' nodes followed by deleting 'n' nodes repeatedly through the list. The function removeNodes accepts a head pointer to the linked list, and two integers, m and n, indicating the numbers of nodes to keep and delete respectively.
Here’s a breakdown of the implementation:
- Initialize
currentto point to the head of the list, which helps traverse the list.previousMNodeis also pointed to the head to assist in linking nodes after deletions. - Use a
whileloop that continues untilcurrentreaches the end of the list (nullptr). - Inside the primary loop, two nested
whileloops manage the skipping and deletion of nodes:- The first
whileloop iterates over 'm' nodes (or until the end of the list), movingcurrentand settingpreviousMNodetocurrentafter each iteration. - The second
whileloop skips 'n' nodes following the m nodes that are kept.currentis moved forward 'n' places.
- The first
- After the iterations, link
previousMNode->nexttocurrentto effectively skip(delete) the 'n' nodes. - Finally, the function returns the head of the modified linked list.
This method changes the linked list in-place with a time complexity of O(m+n) per repetitive sequence until the end and uses O(1) additional space since it modifies the list by rearranging pointers.
class Solution {
public ListNode removeNAfterM(ListNode start, int m, int n) {
ListNode current = start;
ListNode lastPreserved = start;
while (current != null) {
int mCounter = m, nCounter = n;
// Skip m nodes
while (current != null && mCounter != 0) {
lastPreserved = current;
current = current.next;
mCounter--;
}
// Skip n nodes
while (current != null && nCounter != 0) {
current = current.next;
nCounter--;
}
// Connect m-th node to the node after n skipped nodes
lastPreserved.next = current;
}
return start;
}
}
The given Java code defines a method that modifies a linked list by skipping n nodes after every m nodes. This adjustment is achieved through the following sequence:
- Initiate
currentto point to the start of the linked list to traverse through the nodes. - Maintain a reference
lastPreservedthat will help link the nodes that are being kept in the list. - Use a while loop to iterate through the linked list until
currentbecomesnull, meaning the end of the list has been reached. - Employ an inner while loop to bypass
mnodes. It decrements themCountereach time until it reaches zero, effectively movingcurrentforward bymnodes while adjustinglastPreservedto the final node in this segment. - Utilize another inner while loop for skipping a consecutive sequence of
nnodes. It decrements thenCountereach iteration, movingcurrentforward to bypass the nodes meant for deletion. - Link the
lastPreservednode to the node immediately following thennodes that were skipped by updatinglastPreserved.nexttocurrent.
After completing the iterations, the function returns the modified start node of the linked list, effectively reflecting the newly reordered liste without the removed nodes. This method accomplishes node adjustments in a single pass, making it efficient in terms of time and space complexity.