跳到主要内容

First Unique Number

描述

TODO

分析

本题要做到的效果,就是一个队列,但这个队列比较奇怪,只保存不重复的元素,而且如果来了一个元素,导致中间某个元素重复了,要删除中间这个元素。什么数据结构,能做到以O(1)的速度删除中间元素?只能是双向链表。

为了能O(1)的速度访问双向链表中间元素,我们还需要一个HashMap来保存每个元素的位置。这样一看,本题用到的数据结构跟LRU Cache一模一样。

代码

// First Unique Number
class FirstUnique {
private DLinkedList list = new DLinkedList();
private Set<Integer> visited = new HashSet<>();
private Map<Integer, DLinkedNode> m = new HashMap<>();

// O(n)
public FirstUnique(int[] nums) {
for (int num : nums) {
this.add(num);
}
}

// O(1)
public int showFirstUnique() {
DLinkedNode head = list.peekHead();
if (head != null) {
return head.value;
} else {
return -1;
}
}

// O(1)
public void add(int value) {
if (!visited.contains(value)) {
visited.add(value);
DLinkedNode node = new DLinkedNode(value);
list.offerTail(node);
m.put(value, node);
} else {
DLinkedNode node = m.get(value);
list.remove(node);
m.remove(value);
}
}

// Node of doubly linked list
static class DLinkedNode {
int value;
DLinkedNode prev, next;

DLinkedNode(int value) {
this.value = value;
}
}

// Doubly linked list
static class DLinkedList {
DLinkedNode head, tail;
int size;

DLinkedList() {
// head and tail are two dummy nodes
head = new DLinkedNode(0);
tail = new DLinkedNode(0);
head.next = tail;
tail.prev = head;
}

// Add a new node before tail
void offerTail(DLinkedNode node) {
node.next = tail;
node.prev = tail.prev;
tail.prev.next = node;
tail.prev = node;
size++;
}

// Remove a node in the middle
void remove(DLinkedNode node) {
if (node == null) return;
node.prev.next = node.next;
node.next.prev = node.prev;
size--;
}

boolean isEmpty() {
return size == 0;
}

DLinkedNode peekHead() {
return isEmpty()? null:head.next;
}
}
}

相关题目