Design and implement a data structure forLeast Frequently Used (LFU)cache. It should support the following operations:getandput.
get(key)- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value)- Set or insert the value if the key is not already present. When the cache reaches its capacity, it should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when there is a tie (i.e., two or more keys that have the same frequency), the leastrecentlyused key would be evicted.
Follow up:
Could you do both operations inO(1)time complexity?
我的实现绝对不是O(1),O(1)的看了一下discuss,好象是用2个hashmap,一个<key, value>一个<key, node>,然后每个node是个doublelinkedlist,还用了linkedhashset。各种复杂,不明觉厉。过了一段时间做过432那题然后google了一番,终于发现那个数据结构就是实现LFU的数据结构。基本上就是hashmap保存key和node,每个node都存了access次数和对应的hashSet(linkedHashset,因为删除用得最小的值时,old的value会首先被删,这就刚好是linkedhashset的特性,用iterator,先进去的先出来)如果某一个值被access多一次的话,就remove from set,然后插到下一个节点which has + 1 frequency。
public class LFUCache {
class Node {
int key;
int val;
int freq;
long ts;
public Node(int k, int v, int f, long t) {
key = k;
val = v;
freq = f;
ts = t;
}
}
int cap;
//<key, node>
HashMap<Integer, Node> hm;
PriorityQueue<Node> freqQ;
long systime;
public LFUCache(int capacity) {
cap = capacity;
hm = new HashMap<>();
systime = 0L;
freqQ = new PriorityQueue(new Comparator<Node>() {
public int compare(Node n1, Node n2) {
if (n1.freq == n2.freq) {
return (int)(n1.ts - n2.ts);
}
return n1.freq - n2.freq;
}
});
}
public int get(int key) {
if (cap < 1) { // don't need this ?
return -1;
}
if (!hm.containsKey(key)) {
return -1;
}
// if exist update freq & ts
Node cur = hm.get(key);
// need to remove & inseart again to update priorityQueue, or reordering won't kick in
freqQ.remove((Object)cur);
cur.freq = cur.freq + 1; // cur.freq++;
cur.ts = systime++;
freqQ.offer(cur);
return cur.val;
}
public void put(int key, int value) {
if (cap < 1) {
return;
}
if (get(key) != -1) {
Node cur = hm.get(key); // combine into one
cur.val = value; // hm.get(key).val = value;
return;
}
// if it's full, remove least frequnt one
if (freqQ.size() == cap) {
Node old = freqQ.poll();
hm.remove(old.key);
}
// need to create new node and inseart
Node newNode = new Node(key, value, 1, systime++);
hm.put(key, newNode);
freqQ.offer(newNode);
}
}
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache obj = new LFUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/