Skip to content

Remove Duplicates from Sorted List II

Given the head of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers. Return the head of the modified linked list.

InputOutputExplanation
1 → 2 → 3 → 3 → 4 → 4 → 51 → 2 → 5Remove all 3s and 4s (appeared 2+ times)
1 → 1 → 1 → 2 → 32 → 3Remove all 1s
1 → 1(empty)Both nodes are duplicates; return empty list
  • The number of nodes in the list is in the range [0, 300].
  • -100 <= Node.val <= 100
  • The list is guaranteed to be sorted in ascending order.
ApproachTimeSpaceBest When
Hash SetO(n)O(n)First-pass understanding; counting duplicates is intuitive
Single PassO(n)O(1)Memory is limited; elegant pointer manipulation
  • Learn Single Pass first — it demonstrates linked-list traversal and handles the dummy-node pattern.
  • Use Hash Set as a reference: it is easier to visualize and debug, but uses extra space.
Optimal & Elegant
Single Pass
O(n) time · O(1) space
Easy to Understand
Hash Set
O(n) time · O(n) space
★ Recommended

Use a dummy node and a prev pointer. Iterate through the list; when you find a duplicate (current and next have the same value), skip all nodes with that value. Otherwise, advance prev and move to the next node.

⏱ Time O(n) One pass through list 💾 Space O(1) Only pointer variables

Input: 1 → 2 → 3 → 3 → 4 → 4 → 5

StepPrevCurrentActionNote
1dummy11 ≠ 2 → advance prev1 is unique
2122 ≠ 3 → advance prev2 is unique
3233 = 3 → skip all 3sDuplicate detected
4244 = 4 → skip all 4sDuplicate detected
525No next → done5 is unique
Resultdummy → 1 → 2 → 5Duplicates removed

Animated walkthrough

How pointers identify and remove duplicate nodes

Watch as prev marks the last valid node, and current skips all duplicates when consecutive nodes match.

Step 1 of 8
Waiting to begin...
Array state
Memory / lookup state

function deleteDuplicates(head):
dummy = new ListNode(0)
dummy.next = head
prev = dummy
current = head
while current != null:
if current.next != null and current.val == current.next.val:
// Skip all duplicates
value = current.val
while current != null and current.val == value:
current = current.next
// Link prev to the first non-duplicate node
prev.next = current
else:
// Unique node, keep it
prev = prev.next
current = current.next
return dummy.next
remove_duplicates_from_sorted_list_ii_single_pass.py
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def deleteDuplicates(head: Optional[ListNode]) -> Optional[ListNode]:
"""
Remove all nodes with duplicate values from sorted linked list in single pass.
Approach: Use a dummy node and prev pointer. When we find duplicates, skip all nodes
with that value by advancing current and updating prev.next to point past the group.
Time: O(n) — single pass through the list
Space: O(1) — only pointer variables
"""
if not head:
return None
# Create dummy node to handle edge case where head is duplicate
dummy = ListNode(0)
dummy.next = head
prev = dummy
current = head
while current:
# Check if current node is the start of a duplicate group
if current.next and current.val == current.next.val:
# Skip all nodes with the same value
value = current.val
while current and current.val == value:
current = current.next
# Link prev to the first non-duplicate node
prev.next = current
else:
# Current node is unique, keep it
prev = current
current = current.next
return dummy.next
# Test cases
if __name__ == "__main__":
# Helper function to create linked list from array
def create_list(arr):
if not arr:
return None
head = ListNode(arr[0])
current = head
for val in arr[1:]:
current.next = ListNode(val)
current = current.next
return head
# Helper function to convert linked list to array
def list_to_array(head):
result = []
current = head
while current:
result.append(current.val)
current = current.next
return result
# Test case 1: [1,2,3,3,4,4,5]
head1 = create_list([1, 2, 3, 3, 4, 4, 5])
result1 = deleteDuplicates(head1)
print(list_to_array(result1)) # [1, 2, 5]
# Test case 2: [1,1,1,2,3]
head2 = create_list([1, 1, 1, 2, 3])
result2 = deleteDuplicates(head2)
print(list_to_array(result2)) # [2, 3]
# Test case 3: [1,1]
head3 = create_list([1, 1])
result3 = deleteDuplicates(head3)
print(list_to_array(result3)) # []
✓ Simple

First pass: count the frequency of each value using a set or hash map. Second pass: build the result list, skipping any node whose value appeared more than once.

⏱ Time O(n) Two passes 💾 Space O(n) Hash set stores unique values

Input: 1 → 2 → 3 → 3 → 4 → 4 → 5

StepValueFrequencyKeep?
Pass 111Yes
21Yes
32No
42No
51Yes
Pass 2Keep: 1 → 2 → 5
function deleteDuplicates(head):
// Count frequencies
freq = {}
current = head
while current != null:
freq[current.val] = freq.get(current.val, 0) + 1
current = current.next
// Build result list
dummy = new ListNode(0)
dummy.next = head
prev = dummy
current = head
while current != null:
if freq[current.val] == 1:
prev = current
current = current.next
else:
// Skip this node (duplicate)
prev.next = current.next
current = current.next
return dummy.next
remove_duplicates_from_sorted_list_ii_hash_set.py
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def deleteDuplicates(head: Optional[ListNode]) -> Optional[ListNode]:
"""
Remove all nodes with duplicate values from sorted linked list using hash set.
Approach: Count frequency of each value, then rebuild the list with unique values only.
Time: O(n) — two passes through the list
Space: O(n) — hash map stores frequencies
"""
if not head:
return None
# Count frequencies
freq = {}
current = head
while current:
freq[current.val] = freq.get(current.val, 0) + 1
current = current.next
# Build result list with unique values only
dummy = ListNode(0)
dummy.next = head
prev = dummy
current = head
while current:
if freq[current.val] == 1:
# Keep unique node
prev = current
current = current.next
else:
# Skip duplicate node
prev.next = current.next
current = current.next
return dummy.next
# Test cases
if __name__ == "__main__":
# Helper function to create linked list from array
def create_list(arr):
if not arr:
return None
head = ListNode(arr[0])
current = head
for val in arr[1:]:
current.next = ListNode(val)
current = current.next
return head
# Helper function to convert linked list to array
def list_to_array(head):
result = []
current = head
while current:
result.append(current.val)
current = current.next
return result
# Test case 1: [1,2,3,3,4,4,5]
head1 = create_list([1, 2, 3, 3, 4, 4, 5])
result1 = deleteDuplicates(head1)
print(list_to_array(result1)) # [1, 2, 5]
# Test case 2: [1,1,1,2,3]
head2 = create_list([1, 1, 1, 2, 3])
result2 = deleteDuplicates(head2)
print(list_to_array(result2)) # [2, 3]
# Test case 3: [1,1]
head3 = create_list([1, 1])
result3 = deleteDuplicates(head3)
print(list_to_array(result3)) # []
✓ Simple

A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.

⏱ Time O(n) Optimized complexity 💾 Space O(1) Efficient space usage
function approach3():
// Implementation approach goes here
remove_duplicates_from_sorted_list_ii_optimized.py
"""
Solution for Remove Duplicates from Sorted List II
"""
def solve():
"""Implementation for approach 3 of Remove Duplicates from Sorted List II"""
pass
if __name__ == "__main__":
print("Solution ready")