class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
dummy = ListNode(0, head)
prev = dummy
curr = head
while curr:
duplicate = False
while curr.next and curr.val == curr.next.val:
curr = curr.next
duplicate = True
if duplicate:
prev.next = curr.next
else:
prev = prev.next
curr = curr.next
return dummy.next
/**
* 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* deleteDuplicates(ListNode* head) {
ListNode dummy(0, head);
ListNode* prev = &dummy;
ListNode* curr = head;
while (curr) {
bool duplicate = false;
while (curr->next && curr->val == curr->next->val) {
curr = curr->next;
duplicate = true;
}
if (duplicate) {
prev->next = curr->next;
} else {
prev = prev->next;
}
curr = curr->next;
}
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 deleteDuplicates(ListNode head) {
ListNode dummy = new ListNode(0, head);
ListNode prev = dummy;
ListNode curr = head;
while (curr != null) {
boolean duplicate = false;
while (curr.next != null && curr.val == curr.next.val) {
curr = curr.next;
duplicate = true;
}
if (duplicate) {
prev.next = curr.next;
} else {
prev = prev.next;
}
curr = curr.next;
}
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
* @return {ListNode}
*/
var deleteDuplicates = function(head) {
let dummy = new ListNode(0, head);
let prev = dummy;
let curr = head;
while (curr) {
let duplicate = false;
while (curr.next && curr.val === curr.next.val) {
curr = curr.next;
duplicate = true;
}
if (duplicate) {
prev.next = curr.next;
} else {
prev = prev.next;
}
curr = curr.next;
}
return dummy.next;
};
The problem "Remove Duplicates from Sorted List II" asks you to process a singly linked list where the values are sorted in ascending order. Your goal is to remove all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
In other words, if a value appears more than once in the list, you must remove all occurrences of that value, not just the duplicates. The output should be the head of the modified linked list containing only unique values, in sorted order.
head
of a singly linked list.val
and a pointer next
to the next node.At first glance, one might consider traversing the list and removing consecutive duplicates as we go. However, the problem requires us to remove all instances of any value that appears more than once, not just the extra copies. This makes the problem trickier than the classic "remove duplicates" problem.
A naive approach could be to use a hash map to count occurrences, but since the list is already sorted, we can take advantage of this property. By comparing each node to its neighbors, we can detect duplicates in a single pass.
To handle edge cases (such as the head itself being a duplicate), we often use a "dummy" node at the start of the list. This simplifies pointer manipulation and ensures we don't lose track of the new head.
next
points to the head of the list.prev
(initially at dummy) and curr
(at head).curr
has the same value as curr.next
.curr
forward as long as the next node has the same value.prev.next
to curr.next
(skipping all duplicates).prev
forward to curr
.curr
to the next node and repeat until the end of the list.dummy.next
as the new head of the modified list.This approach is efficient because it only requires a single pass through the list and uses no extra memory beyond a few pointers.
Let's consider the input list: 1 -> 2 -> 3 -> 3 -> 4 -> 4 -> 5
1
.1
): Next value is 2
(not a duplicate), so move prev
to 1
.2
): Next value is 3
(not a duplicate), move prev
to 2
.3
): Next value is 3
(duplicate detected). Move curr
forward to skip all 3
s.prev.next
to node after last 3
(which is 4
), removing all 3
s.4
): Next value is 4
(duplicate detected). Move curr
forward to skip all 4
s.prev.next
to node after last 4
(which is 5
), removing all 4
s.5
): No duplicate, move prev
to 5
.
The resulting list is: 1 -> 2 -> 5
O(n)
. Space: O(n)
for the map.O(n)
where n
is the number of nodes.O(1)
(constant extra space).The optimized solution is both time and space efficient, leveraging the sorted property of the input.
In summary, the key to solving "Remove Duplicates from Sorted List II" is recognizing that the sorted property allows us to detect and remove all duplicates in a single pass, using just a few pointers and a dummy node for simplicity. The solution is elegant because it avoids extra space and handles all edge cases, including duplicates at the head and tail, with minimal code.