题目地址:
https://www.lintcode.com/problem/first-unique-number-in-data-stream-ii/description
要求实现一个数据结构,可以实现下面操作:
1、添加一个数字;
2、求按添加顺序来看,第一个只出现过一次的数字。
可以用哈希表 + 链表来做。哈希表key存数字,value存链表节点。我们开两个变量,一个dummy节点,还有一个tail节点,tail节点存链表的最后一个节点。该链表就存所有按添加顺序的且只出现过一次的数字。具体是这样做的。当添加一个数字的时候,先看哈希表的key里有没有,如果有了,那么这个数字再也不可能是唯一数字了,就将其从链表中删除,并将这个数字对应的value存为null,表示该数字永不考虑(如果添加的数字在哈希表里有key,但value是null,则直接返回就行);如果哈希表里没有,则说明该数字是唯一数字,添加到链表结尾。返回唯一数字,其实就是返回dummy.next的value。代码如下:
import java.util.HashMap;
import java.util.Map;
public class DataStream {
class ListNode {
int val;
ListNode prev, next;
public ListNode(int val) {
this.val = val;
}
}
private ListNode dummy, tail;
private Map<Integer, ListNode> map;
public DataStream() {
// do intialization if necessary
map = new HashMap<>();
dummy = tail = new ListNode(0);
}
/**
* @param num: next number in stream
* @return: nothing
*/
public void add(int num) {
// write your code here
if (map.containsKey(num)) {
// 如果哈希表里有num这个key,但value是null,
// 意味着这个num永远不会是唯一数字,直接return
if (map.get(num) == null) {
return;
}
// 否则说明num这个数字之前只出现过一次,这是第二次添加,则将第一次添加的那个节点删掉
ListNode node = map.get(num);
// 其value置为null
map.put(num, null);
node.prev.next = node.next;
// 删除的时候要考虑node自己是不是tail,如果是,则要更新tail
if (node.next != null) {
node.next.prev = node.prev;
} else {
tail = node.prev;
}
} else {
// 如果哈希表里没有num这个key,说明num是第一次见,则加在链表结尾
tail.next = new ListNode(num);
tail.next.prev = tail;
tail = tail.next;
map.put(num, tail);
}
}
/**
* @return: the first unique number in stream
*/
public int firstUnique() {
// write your code here
return dummy.next.val;
}
}
所有操作时间复杂度 O ( 1 ) O(1) O(1),空间复杂度取决于具体输入。