Given the head
of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Return the linked list sorted as well.
Example 1:
Input: head = [1,2,3,3,4,4,5] Output: [1,2,5]
Example 2:
Input: head = [1,1,1,2,3] Output: [2,3]
Constraints:
[0, 300]
.-100 <= Node.val <= 100
The core challenge of this problem is to remove all nodes that have duplicate values from a sorted linked list, ensuring that only distinct values remain. This is significant in scenarios where data integrity and uniqueness are crucial, such as in database management or data processing pipelines.
Common pitfalls include not handling edge cases like an empty list or a list where all elements are duplicates. Misconceptions might arise from misunderstanding the requirement to remove all instances of duplicates, not just one.
To solve this problem, we need to traverse the linked list and identify nodes with duplicate values. A naive solution might involve multiple passes through the list, but this would be inefficient. Instead, we can use a single pass with a dummy node to simplify edge cases.
Here’s a step-by-step approach:
Here’s a detailed breakdown of the algorithm:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def deleteDuplicates(head):
# Create a dummy node to handle edge cases easily
dummy = ListNode(0)
dummy.next = head
prev = dummy
current = head
while current:
# Check if current node is a duplicate
if current.next and current.val == current.next.val:
# Skip all nodes with the same value
while current.next and current.val == current.next.val:
current = current.next
# Link prev node to the node after the last duplicate
prev.next = current.next
else:
# Move prev to current if no duplicate
prev = current
# Move current to the next node
current = current.next
return dummy.next
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 only once. The space complexity is O(1) as we are using a constant amount of extra space.
Consider the following edge cases:
Examples:
Input: head = []
Output: []
Input: head = [1,1,1]
Output: []
Input: head = [1,2,3]
Output: [1,2,3]
To test the solution comprehensively, consider using a variety of test cases, including simple, complex, and edge cases. Python’s unittest framework can be used for this purpose.
import unittest
class TestDeleteDuplicates(unittest.TestCase):
def list_to_linkedlist(self, elements):
dummy = ListNode(0)
current = dummy
for element in elements:
current.next = ListNode(element)
current = current.next
return dummy.next
def linkedlist_to_list(self, head):
elements = []
while head:
elements.append(head.val)
head = head.next
return elements
def test_deleteDuplicates(self):
test_cases = [
([1,2,3,3,4,4,5], [1,2,5]),
([1,1,1,2,3], [2,3]),
([], []),
([1,1,1], []),
([1,2,3], [1,2,3])
]
for input_list, expected_output in test_cases:
head = self.list_to_linkedlist(input_list)
new_head = deleteDuplicates(head)
self.assertEqual(self.linkedlist_to_list(new_head), expected_output)
if __name__ == '__main__':
unittest.main()
When approaching such problems, it’s essential to:
In this blog post, we discussed how to remove duplicates from a sorted linked list efficiently. We covered the problem definition, approach, algorithm, code implementation, complexity analysis, edge cases, and testing. Understanding and solving such problems is crucial for developing strong problem-solving skills in programming.
For further reading and practice, consider the following resources: