Given the head of a singly linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.
Example:
Input: head =[1, 2, 6, 3, 4, 5, 6]
, val = 6 Output:[1, 2, 3, 4, 5]
Your algorithm should run in O(n) time and use O(1) extra space.
The core challenge of this problem is to traverse the linked list and remove nodes that match the given value without disrupting the structure of the list. This problem is significant in various applications such as data cleaning, where unwanted elements need to be removed efficiently.
Potential pitfalls include handling edge cases such as an empty list, all nodes having the target value, or the target value not being present in the list.
To solve this problem, we can use a single pass through the linked list, which ensures an O(n) time complexity. We will maintain a pointer to the current node and a pointer to the previous node to help with node removal.
Here is a step-by-step approach:
Here is a detailed breakdown of the algorithm:
#include <iostream>
using namespace std;
// 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* removeElements(ListNode* head, int val) {
// Create a dummy node that points to the head
ListNode* dummy = new ListNode(0, head);
ListNode* prev = dummy;
ListNode* curr = head;
// Traverse the list
while (curr != nullptr) {
if (curr->val == val) {
// Remove the current node
prev->next = curr->next;
} else {
// Move prev to curr
prev = curr;
}
// Move curr to the next node
curr = curr->next;
}
// Return the new head
ListNode* newHead = dummy->next;
delete dummy; // Free the dummy node
return newHead;
}
};
// Helper function to print the list
void printList(ListNode* head) {
while (head != nullptr) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
// Main function to test the solution
int main() {
// Create a linked list: 1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6
ListNode* head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(6);
head->next->next->next = new ListNode(3);
head->next->next->next->next = new ListNode(4);
head->next->next->next->next->next = new ListNode(5);
head->next->next->next->next->next->next = new ListNode(6);
// Print the original list
cout << "Original list: ";
printList(head);
// Remove elements with value 6
Solution solution;
head = solution.removeElements(head, 6);
// Print the modified list
cout << "Modified list: ";
printList(head);
return 0;
}
The time complexity of this approach is O(n), where n is the number of nodes in the linked list. This is because we traverse the list once. The space complexity is O(1) as we are using only a few extra pointers and not any additional data structures.
Consider the following edge cases:
These cases are handled by the algorithm as it traverses the entire list and adjusts pointers accordingly.
To test the solution comprehensively, consider the following test cases:
[]
[6, 6, 6]
[1, 2, 3]
[1, 2, 6, 3, 4, 5, 6]
Use a variety of test cases to ensure the solution handles all scenarios correctly.
When approaching such problems, consider the following tips:
In this blog post, we discussed how to remove elements from a linked list in O(n) time complexity using C++. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for improving your coding skills and preparing for technical interviews.
For further reading and practice, consider the following resources: