数据流中第一个独特的数 II (lint960)——哈希
数据流中第一个独特的数 II
描述
我们需要实现一个叫 DataStream
的数据结构。并且这里有两个方法需要实现:
void add(number)
// 加一个新的数int firstUnique()
// 返回第一个独特的数
你可以假设在调用 firstUnique 方法时,数据流中至少有一个独特的数字
样例
输入:
add(1)
add(2)
firstUnique()
add(1)
firstUnique()
输出:
[1,2]
题解1:HashMap + List
HashMap:存储数字出现的次数
List: 顺序存储添加的数字
class DataStream {
private HashMap<Integer, Integer> map;
private List<Integer> list;
public DataStream() {
list = new ArrayList<>();
map = new HashMap<>();
}
public void add(int num) {
list.add(num);
map.put(num, map.getOrDefault(num, 0) + 1);
}
public int firstUnique() {
for (Integer num : list) {
if (map.get(num) == 1) {
return num;
}
}
return -1;
}
}
题解2:Queue + Set
Queue: 按添加顺序保存只出现一次的数
Set: 数据流中已有的数
class DataStream {
private Queue<Integer> queue;
private Set<Integer> set;
public DataStream() {
queue = new ArrayDeque<>();
set = new HashSet<>();
}
public void add(int num) {
if(set.contains(num)) {
queue.remove(num);
return;
}
set.add(num);
queue.add(num);
}
public int firstUnique() {
if(queue.size() == 0) {
return -1;
}
return queue.peek();
}
}
题解3: ListNode链表 + HashMap+ Set
ListNode链表:按添加顺序存储只出现一次的数
HashMap<Integer, ListNode>:保存数的前节点
Set: 保存出现2次以上的数
class DataStream {
private ListNode dummy; //哨兵节点
private ListNode tail; //尾结点
private Map<Integer, ListNode> pres;
private Set<Integer> set;
public DataStream() {
dummy = new ListNode(0);
tail = dummy;
pres = new HashMap<>();
set = new HashSet<>();
}
public int firstUnique() {
if(dummy.next == null) {
return -1;
}
return dummy.next.val;
}
public void add(int num) {
if(set.contains(num)) return;
if(pres.containsKey(num)) {
remove(num);
set.add(num);
}else {
ListNode node = new ListNode(num);
pres.put(num, tail);
tail.next = node;
tail = node;
}
}
public void remove(int num) {
ListNode p = pres.get(num);
p.next = p.next.next;
pres.remove(num);
if(p.next != null) {
pres.put(p.next.val, p);
}else {
tail = p;
}
}
}