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
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to removing duplicate nodes from a sorted list involves checking every node to see if it's part of a sequence of duplicate values. If it is, we skip over the entire sequence when building our new list. Otherwise, we keep the node and add it to our new list.
Here's how the algorithm would work step-by-step:
def remove_duplicates_from_sorted_list_ii_brute_force(head):
dummy_node = ListNode(0)
tail_of_new_list = dummy_node
current_node = head
while current_node:
# Check for duplicate sequence
if current_node.next and current_node.val == current_node.next.val:
duplicate_value = current_node.val
# Advance to the end of the duplicate sequence
while current_node and current_node.val == duplicate_value:
current_node = current_node.next
else:
# Attach node because it's unique
tail_of_new_list.next = current_node
tail_of_new_list = tail_of_new_list.next
current_node = current_node.next
# Terminate the new list
tail_of_new_list.next = None
return dummy_node.next
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
The goal is to go through a sorted list and remove any numbers that appear more than once. The optimal approach involves carefully checking each number and linking around any sequence of repeated numbers, avoiding the need to repeatedly search the list.
Here's how the algorithm would work step-by-step:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def remove_duplicates_from_sorted_list_ii(head):
dummy_node = ListNode(0)
dummy_node.next = head
previous_node = dummy_node
current_node = head
while current_node:
# Check for duplicates by comparing current with next
if current_node.next and current_node.val == current_node.next.val:
# Found duplicate sequence
# Move past all duplicates
while current_node.next and current_node.val == current_node.next.val:
current_node = current_node.next
# Need to skip duplicate sequence
previous_node.next = current_node.next
else:
# No duplicates, move along
previous_node = current_node
current_node = current_node.next
# Return list starting after dummy node
return dummy_node.next
Case | How to Handle |
---|---|
Empty list (head is null) | Return null immediately as there are no nodes to process. |
List with a single node | Return the head directly, as a single node cannot have duplicates. |
List with only two nodes and they are duplicates | Return null as both nodes must be removed. |
List with only two nodes and they are distinct | Return the original head as no duplicates exist. |
List with all nodes having the same value | Return null as all nodes are duplicates and must be removed. |
Duplicates at the beginning of the list | The dummy node handles removal of the initial duplicated node(s) correctly. |
Duplicates at the end of the list | The algorithm correctly identifies and removes the trailing duplicates. |
Large list with many duplicate sequences | The iterative approach ensures the solution can handle large lists efficiently without stack overflow issues. |