Linked List · Medium

245. Remove Duplicates From an Unsorted Linked List

Topics: Linked List, Hashing

Solve it on DeVert Campus - free code runner

Problem

A singly linked list contains n integer values, not necessarily sorted, possibly with duplicates anywhere in the list. Remove every node whose value already appeared earlier in the list, keeping only the first occurrence of each value in its original position. Print the result.

Input and output

Input: The first line contains an integer n. The second line contains n space-separated integers, not necessarily sorted and possibly containing duplicates. Output: Print the remaining values after removing later duplicates, in their original order, space-separated.

Example

Input:
6
1 2 1 3 2 4
Output:
1 2 3 4

Constraints

1 <= n <= 10^5

Key observation

This is the direct 'no sortedness guarantee' counterpart to the sorted-list version - comparing the two side by side is a great way to internalize exactly what sortedness buys you algorithmically.

Intuition

Remove duplicate values from a linked list that ISN'T sorted, keeping only the first occurrence of each value. Brute force: For every node, scan every OTHER node in the list directly to check if its value repeats earlier - this costs O(n²), too slow for large lists, and unnecessary given hash sets provide O(1) lookups. Optimised: Since the list isn't sorted, duplicates can appear ANYWHERE, so adjacent-only comparisons (as used for the sorted version) don't work here - a hash set of values already seen lets you decide in O(1) whether to keep or delete each node in a single linear pass, at the cost of O(n) extra memory.

Brute Force - Compare Against All Earlier Nodes

Walk the list with a pointer, and for every node, scan all nodes that come before it in the list to check whether its value already appeared; if it has, unlink the current node from the list. This preserves the required original order of first occurrences since nothing is reordered, only removed, but comparing against every earlier node for every node makes it quadratic. Time: O(n^2) Space: O(1)

Better - Balanced BST / Ordered Set of Seen Values

Walk the list once, maintaining a self-balancing ordered set (such as a TreeSet) of values already seen. For each node, check membership in O(log n); if the value is already present, unlink the node, otherwise insert its value into the set and move on. Because membership queries take only O(log n) instead of a full O(n) rescan of prior nodes, and the list is never sorted or reordered (so the required original positions of first occurrences are preserved), this is a genuine improvement over the brute force while remaining fully correct for this problem. Time: O(n log n) Space: O(n)

Optimal - Single Pass With a Hash Set

Walk the list once, maintaining a hash set of values already seen. For each node, check membership in the hash set in O(1) average time; if present, unlink the current node from the list, otherwise add its value to the set. This keeps every first occurrence exactly in its original position (never sorting the list, which would violate the problem's ordering requirement) while doing only a single linear pass with constant-time lookups, the best possible approach short of an algorithm that avoids extra space entirely. Time: O(n) Space: O(n)

Step by step

1. Maintain a hash set of every value already seen so far. 2. Walk the list once: for each node, if its value is ALREADY in the seen set, unlink (delete) it; otherwise, add its value to the seen set and move on.

Complexity

Time: O(n) - one single pass, with O(1) hash-set lookups at each node. Space: O(n), for the hash set of seen values (the necessary tradeoff for handling unsorted duplicates efficiently).

Edge cases

n = 1 (no duplicates possible), a list where every value is identical (only the first survives), and n = 10^5 for performance.

Interview tip

Be ready to state clearly WHY the sorted version's O(1)-space trick (checking only adjacent nodes) doesn't apply here - the lack of ordering is exactly what forces the O(n) hash-set memory tradeoff.

All DSA problems