Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
andput
.
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 reached its capacity, it should invalidate the least recently used item before inserting a new item.
Follow up:
Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 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.put(4, 4); // evicts key 1 cache.get(1); // returns -1 (not found) cache.get(3); // returns 3 cache.get(4); // returns 4
class LRUCache { private: typedef list<int> LI; //双向链表,已知数据指针的情况下,删除和插入到链表头的时间都为O(1)。用STL中的list实现, typedef pair<int,LI::iterator> PII;//哈希表中key->value的结构为hash[key]=(value,iterator) typedef unordered_map<int,PII> HASH; LI cachelist; HASH mp; int _capacity; public: LRUCache(int capacity) :_capacity(capacity){ } int get(int key) { if(mp.count(key)){ int value=mp[key].first; cachelist.erase(mp[key].second); cachelist.push_front(key); mp[key].second=cachelist.begin(); return value; }else{ return -1; } } void put(int key, int value) { if(mp.count(key)){ mp[key].first=value; cachelist.erase(mp[key].second); cachelist.push_front(key); mp[key].second=cachelist.begin(); }else{ if(cachelist.size()==_capacity){ LI::iterator it=cachelist.end();--it; int delkey=*it; cachelist.erase(it); mp.erase(delkey); }//这里千万别用else,否则链表满了的时候不会再插入新key。 cachelist.push_front(key); mp[key].first=value; mp[key].second=cachelist.begin(); } } }; /** * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following operations:
get
andput
.
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 in O(1) time complexity?Example:
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 { public: LFUCache(int capacity) { cap = capacity; } int get(int key) { if (m.count(key) == 0) return -1; freq[m[key].second].erase(iter[key]); ++m[key].second; freq[m[key].second].push_back(key); iter[key] = --freq[m[key].second].end(); if (freq[minFreq].size() == 0) ++minFreq; return m[key].first; } void put(int key, int value) { if (cap <= 0) return; if (get(key) != -1) { m[key].first = value; return; } if (m.size() >= cap) { m.erase(freq[minFreq].front()); iter.erase(freq[minFreq].front()); freq[minFreq].pop_front(); } m[key] = {value, 1}; freq[1].push_back(key); iter[key] = --freq[1].end(); minFreq = 1; } private: int cap, minFreq; unordered_map<int, pair<int, int>> m;//key->(value,f) unordered_map<int, list<int>> freq;//freq->list unordered_map<int, list<int>::iterator> iter;//key->iter };