Challenge: Perform all these in O(1) time complexity.
这题,感觉想出了方法,处理起来还是挺麻烦的。看到要按key来取,还O(1),所以一定有hashmap。要达到O(1)取max,min,一开始想heap,但heap的话,插入跟删除都得logn。后来网上看到可以用double linkedlist。一开始没想通,插入删除都O(n)呀。后来发现,因为值只会+1/-1,所以每次只要从hashmap里取得node,然后处理前一个点或者后一个点就ok了。每个节点都存储了这个频率所拥有的key,然后map里存着key与相对node。max跟min就是链表的最后一个节点和最开始一个节点。插个图好理解点。
Copy public class AllOne {
HashMap < String , Node > hm;
Node head;
Node tail;
/** Initialize your data structure here. */
public AllOne () {
head = new Node() ;
tail = new Node() ;
head . freq = Integer . MIN_VALUE ;
tail . freq = Integer . MAX_VALUE ;
head . next = tail;
tail . prev = head;
hm = new HashMap <>();
}
/** Inserts a new key <Key> with value 1. Or increments an existing key by 1. */
public void inc ( String key) {
if ( ! hm . containsKey (key)) {
addToFirst(key) ;
} else {
moveRight(key) ;
}
}
/** Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. */
public void dec ( String key) {
if ( ! hm . containsKey (key)) {
return ;
}
moveLeft(key) ;
}
private void addToFirst ( String key) {
if ( head . next . freq > 1 ) {
Node newNode = new Node() ;
newNode . freq = 1 ;
newNode . next = head . next ;
head . next = newNode;
newNode . next . prev = newNode;
newNode . prev = head;
newNode . values . add (key);
hm . put (key , newNode);
} else {
head . next . values . add (key);
hm . put (key , head . next );
}
}
private void moveRight ( String key) {
Node cur = hm . get (key);
// make new node to store value
if ( cur . next . freq > cur . freq + 1 ) {
Node newNode = new Node() ;
newNode . freq = cur . freq + 1 ;
newNode . next = cur . next ;
cur . next = newNode;
newNode . next . prev = newNode;
newNode . prev = cur;
}
cur . next . values . add (key);
hm . put (key , cur . next );
cur . values . remove (key);
if ( cur . values . size () == 0 ) {
remove(cur) ;
}
}
private void moveLeft ( String key) {
Node cur = hm . get (key);
if ( cur . freq - 1 == 0 ) {
hm . remove (key);
}
if ( cur . freq - 1 > 0 && cur . prev . freq < cur . freq - 1 ) {
// create node
Node newNode = new Node() ;
newNode . freq = cur . freq - 1 ;
newNode . prev = cur . prev ;
cur . prev = newNode;
newNode . prev . next = newNode;
newNode . next = cur;
}
if ( cur . prev . freq > 0 ) {
cur . prev . values . add (key);
hm . put (key , cur . prev );
}
cur . values . remove (key);
if ( cur . values . size () == 0 ) {
remove(cur) ;
}
}
private void remove ( Node cur) {
cur . prev . next = cur . next ;
cur . next . prev = cur . prev ;
}
/** Returns one of the keys with maximal value. */
public String getMaxKey () {
if ( tail . prev == head) {
return "" ;
}
return tail . prev . values . iterator () . next ();
}
/** Returns one of the keys with Minimal value. */
public String getMinKey () {
if ( head . next == tail) {
return "" ;
}
return head . next . values . iterator () . next ();
}
}
class Node {
int freq;
HashSet < String > values = new HashSet <>();
Node prev;
Node next;
}
/**
* Your AllOne object will be instantiated and called as such:
* AllOne obj = new AllOne();
* obj.inc(key);
* obj.dec(key);
* String param_3 = obj.getMaxKey();
* String param_4 = obj.getMinKey();
*/