Remove Duplicates from Sorted List II

MediumLinked List · Dummy Head · Run Skipping🧩 Linked List TechniquesLeetCode #82 ↗Updated

Problem

You are given the head of a linked list sorted in ascending order. Delete every node whose value appears more than once — not just the extra copies, all of them — so only values that occurred exactly once remain. Return the resulting list, still sorted.
Input[1,2,3,3,4,4,5]Output[1,2,5]
Input[1,1,1,2,3]Output[2,3]
Input[2,2]Output[]

0 ≤ n ≤ 300  ·  -100 ≤ Node.val ≤ 100  ·  list is sorted ascending

Try it yourself

Java
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Because the list is sorted, duplicates form contiguous runs. Keep a pointer prev to the last node known to be unique (starting at a dummy) and, whenever a run of length ≥ 2 starts, jump past the whole run and link prev to whatever follows.
PatternLinked List Techniques

Instinct Nodes joined by next pointers and the task is to reverse, splice, merge, reorder or remove in place - grab a dummy head and rewire pointers carefully.

Memory hack Save next, flip, step - never let go of a rope before you've grabbed the next one.

Open the Linked List Techniques guide →

Approaches

Brute ForceCount Frequencies, Keep Singletons

Time O(n)Space O(n)

First pass: count how often each value occurs in a hash map. Second pass: append to a new chain only nodes whose count is exactly 1. This ignores the sorted order entirely, so it would even work on unsorted input.

Java
public ListNode deleteDuplicates(ListNode head) {
    Map<Integer, Integer> count = new HashMap<>();
    for (ListNode c = head; c != null; c = c.next) count.merge(c.val, 1, Integer::sum);
    ListNode dummy = new ListNode(0), tail = dummy;
    for (ListNode c = head; c != null; c = c.next) {
        if (count.get(c.val) == 1) {
            tail.next = c;
            tail = c;
        }
    }
    tail.next = null; // cut off any trailing duplicates
    return dummy.next;
}

Straightforward, but the map costs O(n) memory that sortedness makes unnecessary.

At a glance

LevelApproachTimeSpace
Brute ForceCount Frequencies, Keep SingletonsO(n)O(n)
BetterRecursion on the Remaining ListO(n)O(n)
OptimalDummy Head + Iterative Run SkippingO(n)O(1)
Common pitfalls
  • Keeping one copy of a duplicated value (that is problem 83, not this one).
  • Advancing prev right after deleting a run — misses back-to-back runs like [1,1,2,2].
  • Special-casing the head instead of using a dummy — easy to get wrong when the head is duplicated.
Interview tips
  • Contrast with Remove Duplicates I (83) to show you read the statement carefully.
  • Use the sortedness: duplicates are adjacent, so no map is needed.
  • Test aloud: all duplicates, duplicates at head, duplicates at tail, no duplicates.
Pattern
Dummy head + prev/cur → delete nodes (including the head) from a linked list in one pass.
My notes saved in this browser