2.1. remove duplicates in linked list
This commit is contained in:
parent
73612d7725
commit
3fa26388cb
|
|
@ -0,0 +1,166 @@
|
|||
# 2.1. Remove duplicates
|
||||
|
||||
## Write code to remove duplicates from an unsorted linked list. Follow up: solve it without a temporary buffer
|
||||
|
||||
> example: ll = [3,2,1,3]
|
||||
|
||||
## 2.1.1. First idea
|
||||
|
||||
Will try a temporary buffer first. I don't see how the implementation differs from a simple list with O(n). Starter code:
|
||||
|
||||
```java
|
||||
class Node {
|
||||
Node next = null;
|
||||
int data;
|
||||
|
||||
public Node(int d){
|
||||
data = d,
|
||||
}
|
||||
|
||||
void appendToTail(int d){
|
||||
Node end = new Node(d);
|
||||
Node n = this;
|
||||
while (n.next != null){
|
||||
n = n.next
|
||||
}
|
||||
n.next = end;
|
||||
}
|
||||
}
|
||||
|
||||
Node a = new Node(3);
|
||||
Node b = new Node(2);
|
||||
Node d = new Node(1);
|
||||
Node c = new Node(3);
|
||||
a.appendTotail(b);
|
||||
b.appendToTail(c);
|
||||
c.appendToTail(d);
|
||||
```
|
||||
|
||||
Then iterate through the nodes, keep a list of visited_numbers. if current node is in this list, remove element and point .next to the next element.
|
||||
|
||||
```java
|
||||
void remove_duplicates(Node a){
|
||||
visited = new ArrayList();
|
||||
if (a == null){
|
||||
return;
|
||||
}
|
||||
visited.add(a.data);
|
||||
Node current = a;
|
||||
while(current.next != null){
|
||||
if (current.next.next == null){
|
||||
return;
|
||||
}
|
||||
if visited.contains(current.next.data){
|
||||
current.next = current.next.next;
|
||||
current = current.next.next;
|
||||
}
|
||||
else{
|
||||
current = current.next;
|
||||
visited.add(current.next.data);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
Basically delegiting an element in a linked list is moving the .next of the previous node to the next (in a singly linked list). If the next node is null, that is, if the current node is the last one, then jus return. Ideally I'd return the head, first node. But can't be done in a single linked list.
|
||||
|
||||
## 2.1.2. Follow up: solve it without a temporary buffer
|
||||
|
||||
Temporary buffer I assume it's the array of visited numbers, or the temprary Node? I think temporary node. I can just reuse `a`?
|
||||
|
||||
```java
|
||||
void remove_duplicates(Node a){
|
||||
visited = new ArrayList();
|
||||
if (a == null){
|
||||
return;
|
||||
}
|
||||
visited.add(a.data);
|
||||
while(a.next != null){
|
||||
if (a.next.next == null){
|
||||
return;
|
||||
}
|
||||
if visited.contains(a.next.data){
|
||||
a.next = a.next.next;
|
||||
a = a.next.next;
|
||||
}
|
||||
else{
|
||||
a = a.next;
|
||||
visited.add(a.next.data);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
Which should work equally fine.
|
||||
|
||||
## Hints
|
||||
|
||||
### Hint 1
|
||||
|
||||
> Try using a hash table, should be able to do this in a single pass of the linked list
|
||||
|
||||
Haven't used a hash table but a set of visited numbers, and I already do it in a single pass of the linked list.
|
||||
|
||||
### Hint 2
|
||||
|
||||
> Without extra space, you need O(N<sup>2</sup>) time. Use two pointers, where the second one searches ahead of the first one
|
||||
|
||||
Why do I need O(N<sup>2</sup>) time... My implementation is O(N). Doing something wrong? I guess my second pointer is just called `a.next`. There must be something I'm missing
|
||||
|
||||
## Solution
|
||||
|
||||
In order to remove duplicates, need to track duplicates --> hash table.
|
||||
|
||||
Iterate through the linked list, adding each element to the hash table. If there's a duplicate element, remove it and continue iterating. O(N) time.
|
||||
|
||||
```java
|
||||
void deleteDups(LinkedListNode n){
|
||||
HashSet<Integer> set = new HashSet<Integer>();
|
||||
LinkedListNode previous = null;
|
||||
while(n != null){
|
||||
if(set.contains(n.data)){
|
||||
previous.next = n.next;
|
||||
}
|
||||
else{
|
||||
set.add(n.data);
|
||||
previous = n;
|
||||
}
|
||||
n = n.next;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Follow up: no buffer allowed
|
||||
|
||||
Iterate with two pointers: current, iterating through the linked list, and runner, checking all subsequent nodes for duplicates.
|
||||
|
||||
```java
|
||||
void deleteDups(LinkedListNode head){
|
||||
LinkedListNode current = head;
|
||||
while(current != null){
|
||||
/* Remove all future nodes with the same value */
|
||||
LinkedListNode runner = current;
|
||||
while(runner != null){
|
||||
if(runner.next.data == current.data){
|
||||
runner.next = runner.next.next;
|
||||
}
|
||||
else{
|
||||
runner = runner.next;
|
||||
}
|
||||
}
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Buffer meant HashTable, ok yes then we need to check all the linked list for each element in the linked list, hence O(N<sup>2</sup>) time.
|
||||
|
||||
Code runs in O(1) space, but (N<sup>2</sup>) time.
|
||||
|
||||
## Resources
|
||||
|
||||
* [Java solution](https://github.com/careercup/CtCI-6th-Edition/blob/master/Java/Ch%2002.%20Linked%20Lists/Q2_01_Remove_Dups/QuestionA.java)
|
||||
* [C++ solution](https://github.com/careercup/CtCI-6th-Edition-cpp/blob/a68ba3e1c630a4d218ff1294f3eaf5aeced449ec/chapter-2-Linked-Lists/2-1-remove-dups.cpp)
|
||||
* [Python solution](https://github.com/careercup/CtCI-6th-Edition-Python/blob/e6bc732588601d0a98e5b1bc44d83644b910978d/Chapter2/LinkedList.py)
|
||||
|
|
@ -26,7 +26,7 @@ class Node {
|
|||
}
|
||||
|
||||
Node a = new Node(5);
|
||||
Node b = new Node (7);
|
||||
Node b = new Node(7);
|
||||
a.appendTotail(b);
|
||||
```
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue