Design and implement a data structure for Least 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 least recently used key would be evicted.
Follow up:
Could you do both operations inO(1)time complexity?
/* Increasing frequencies ----------------------------->+------+ +---+ +---+ +---+| Head |----| 1 |----| 5 |----| 9 | Frequencies+------+ +-+-+ +-+-+ +-+-+ | | | +-+-+ +-+-+ +-+-+ | |2,3| |4,3| |6,2| | +-+-+ +-+-+ +-+-+ | Most recent | | | +-+-+ +-+-+ | key,value pairs |1,2| |7,9| | +---+ +---+ v*/classLFUCache {classEntry {int key;int val;int count;Entry(int k,int v,int c) { key = k; val = v; count = c; } }// for key and valueprivateHashMap<Integer,Entry> cache;// for freq and elemsprivateHashMap<Integer,LinkedHashSet<Entry>> countMap;// capacityprivateint capacity;// min freqprivateint min =-1;publicLFUCache(int capacity) {this.capacity= capacity; cache =newHashMap<>(); countMap =newHashMap<>();countMap.put(1,newLinkedHashSet<>()); }publicintget(int key) {// key not foundif (!cache.containsKey(key)) {return-1; }// remove in the original freqEntry e =cache.get(key);countMap.get(e.count).remove(e);// min is evicted up, then min needs add oneif (e.count== min &&countMap.get(e.count).isEmpty()) {countMap.remove(e.count); min++; }//update the freq after adding onee.count++;if (!countMap.containsKey(e.count)) {countMap.put(e.count,newLinkedHashSet<>()); }countMap.get(e.count).add(e);returne.val; }publicvoidput(int key,int value) {if (capacity <=0) return;// 1. having the key then we update (need to get(key) to add freq)if (cache.containsKey(key)) {Entry e =cache.get(key);e.val= value;get(key);return; }// 2. evicting the least freq oneif (cache.size() == capacity) {Iterator<Entry> it =countMap.get(min).iterator();Entry e =it.next();it.remove();cache.remove(e.key);// set empty then remove keyif (!it.hasNext()) countMap.remove(min); }// 3. new one is createdEntry newE =newEntry(key, value,1);cache.put(key, newE); min =1;// for the case we remove 1if (!countMap.containsKey(1)) {countMap.put(1,newLinkedHashSet<>()); }countMap.get(1).add(newE); }}/** * 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); */