Write code to remove duplicates from an unsorted linked list.
Example1:
Input: [1, 2, 3, 3, 2, 1]
Output: [1, 2, 3]
Example2:
Input: [1, 1, 1, 1, 2]
Output: [1, 2]
Note:
The length of the list is within the range[0, 20000].
The values of the list elements are within the range [0, 20000].
Follow Up:
How would you solve this problem if a temporary buffer is not allowed?
Solutions
Solution 1: Hash Table
Thinking
Duplicate values must be removed while keeping the first occurrence. Scanning the suffix for every node is \(O(n^2)\), fine for short lists but linear per query.
“Has this value appeared?” is a lookup; a hash table makes it expected constant time.
\(vis\) stores kept values and a dummy \(pre\) simplifies deletion: skip \(pre.next\) when its value is already in the set, otherwise record it and advance. One pass removes duplicates.
We create a hash table \(vis\) to record the values of the nodes that have been visited.
Then we create a dummy node \(pre\) such that \(pre.next = head\).
Next, we traverse the linked list. If the value of the current node is already in the hash table, we delete the current node, i.e., \(pre.next = pre.next.next\); otherwise, we add the value of the current node to the hash table and move \(pre\) to the next node.
After the traversal, we return the head of the linked list.
The time complexity is \(O(n)\), and the space complexity is \(O(n)\). Here, \(n\) is the length of the linked list.
1 2 3 4 5 6 7 8 9101112131415161718
# Definition for singly-linked list.# class ListNode:# def __init__(self, x):# self.val = x# self.next = NoneclassSolution:defremoveDuplicateNodes(self,head:ListNode)->ListNode:vis=set()pre=ListNode(0,head)whilepre.next:ifpre.next.valinvis:pre.next=pre.next.nextelse:vis.add(pre.next.val)pre=pre.nextreturnhead
1 2 3 4 5 6 7 8 910111213141516171819202122
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */classSolution{publicListNoderemoveDuplicateNodes(ListNodehead){Set<Integer>vis=newHashSet<>();ListNodepre=newListNode(0,head);while(pre.next!=null){if(vis.add(pre.next.val)){pre=pre.next;}else{pre.next=pre.next.next;}}returnhead;}}
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */funcremoveDuplicateNodes(head*ListNode)*ListNode{vis:=map[int]bool{}pre:=&ListNode{0,head}forpre.Next!=nil{ifvis[pre.Next.Val]{pre.Next=pre.Next.Next}else{vis[pre.Next.Val]=truepre=pre.Next}}returnhead}