Skip to main content

63. Remove Duplicates from Sorted List II

mediumAsked at Plaid

Delete all nodes in a sorted linked list that have duplicate values, keeping only unique values. Plaid asks this because removing transactions that have any duplicate occurrences (not keeping one) is a stricter dedup needed for audit logs.

By Alex Chen, Founder, InterviewChamp.AI · Last verified

Source citations

Public interview reports confirming this problem appears in Plaid loops.

  • LeetCode Discuss (2026)Plaid OA list dedup.
  • Glassdoor (2025)Plaid SWE II screen.

Problem

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.

Constraints

  • 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.

Examples

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]

Approaches

1. Collect values, filter, rebuild

Walk into array, count, rebuild with only unique values.

Time
O(n)
Space
O(n)
// Allocates a new list. Mention as warm-up.

Tradeoff: Works but allocates.

2. Dummy head + lookahead skip

Dummy head. Use prev to track the last kept node. For each candidate, peek ahead — if next has the same value, skip all matching nodes.

Time
O(n)
Space
O(1)
function deleteDuplicates(head) {
  const dummy = { next: head };
  let prev = dummy;
  while (prev.next) {
    let curr = prev.next;
    if (curr.next && curr.next.val === curr.val) {
      const v = curr.val;
      while (curr && curr.val === v) curr = curr.next;
      prev.next = curr;
    } else {
      prev = prev.next;
    }
  }
  return dummy.next;
}

Tradeoff: Single pass, in-place. The dummy head simplifies removal of the head node. The 'skip all matching' inner loop ensures we remove all copies, not just one.

Plaid-specific tips

Plaid grades this on whether prev stays put when we delete a run. Don't advance prev until you've confirmed the current node is unique. Bonus signal: connect to audit-log strict dedup — when a transaction has any duplicate, all copies are quarantined for manual review.

Common mistakes

  • Advancing prev even when the current run is deleted — leaves dangling references.
  • Forgetting the dummy head — removing the head node is awkward without one.
  • Using if/else but writing the same advancement in both branches — easy mistake.

Follow-up questions

An interviewer at Plaid may pivot to one of these next:

  • Remove Duplicates from Sorted List (LC 83) — keep one of each.
  • Same problem on an unsorted list.
  • Stream version where nodes arrive one at a time.

Solve it now

Free. No sign-up. Python and JavaScript run instantly in your browser.

Output

Press Run or Cmd+Enter to execute

FAQ

Why not advance prev unconditionally?

When the current node is part of a duplicate run, we delete the whole run including curr. The new prev.next is the post-run node, which we still need to validate.

Why a dummy head?

Removes the special case where the original head is part of a duplicate run.

Practice these live with InterviewChamp.AI

Drill Remove Duplicates from Sorted List II and other Plaid interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.

Practice these live with InterviewChamp.AI →