Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations: get
and put
.java
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 least recently used key would be evicted.node
Follow up:
Could you do both operations in O(1) time complexity?ui
Example:this
LFUCache cache = new LFUCache( 2 /* capacity */ ); cache.put(1, 1); cache.put(2, 2); cache.get(1); // returns 1 cache.put(3, 3); // evicts key 2 cache.get(2); // returns -1 (not found) cache.get(3); // returns 3. cache.put(4, 4); // evicts key 1. cache.get(1); // returns -1 (not found) cache.get(3); // returns 3 cache.get(4); // returns 4
class LFUCache { HashMap<Integer, Node> map = new HashMap<>(); HashMap<Integer, LinkedHashSet<Node>> fre = new HashMap<>(); int cap; int size; int min = 0; public LFUCache(int capacity) { this.cap = capacity; } public int get(int key) { if (!map.containsKey(key)) { return -1; } Node cur = map.remove(key); int fr = cur.f; fre.get(cur.f).remove(cur); if (fre.containsKey(fr) && fre.get(fr).isEmpty() && min == fr) { min++; fr++; } cur.f++; if (!fre.containsKey(cur.f)) { fre.put(cur.f, new LinkedHashSet<Node>()); } map.put(key, cur); fre.get(cur.f).add(cur); return cur.v; } public void put(int key, int value) { if (cap < 1) { return; } if (map.containsKey(key)) { map.get(key).v = value; get(key); } else{ if (size >= cap) { Node discard = fre.get(min).iterator().next(); map.remove(discard.k); fre.get(min).remove(discard); size--; } Node cur = new Node(key, value, 1); map.put(key, cur); if(!fre.containsKey(1)) { fre.put(1, new LinkedHashSet<>()); } fre.get(1).add(cur); min = 1; size++; } } } class Node { int k; int v; int f; Node(int k, int v, int f) { this.k = k; this.v = v; this.f = f; } }