460. LFU缓存
460. LFU缓存
有一个疑问,当我的构造函数这个样定义的时候
Node(int _cnt, int _time, int _key, int _value) { cnt = _cnt; time = _time; key = _key; value = _value; }
我这样调用unordered_map是不会通过编译
int get(int key) { if(capacity == 0) { return -1; } auto it = key_value.find(key); if(it == key_value.end()) { return -1; } Node cache = key_value[key]; // 这一行不能通过编译,cache通过it->second却是能够正常赋值的 s.erase(cache); cache.cnt++; cache.time = ++time; s.insert(cache); it->second = cache; return cache.value; }
但是,当我构造函数这个样定义的时候
Node(){} Node(int _cnt, int _time, int _key, int _value) { cnt = _cnt; time = _time; key = _key; value = _value; }
Node cache = key_value[key];
却能够正确编译,记录一下
代码:
1 struct Node { 2 int cnt; 3 int time; 4 int key, value; 5 6 Node(){} 7 Node(int _cnt, int _time, int _key, int _value) { 8 cnt = _cnt; 9 time = _time; 10 key = _key; 11 value = _value; 12 } 13 14 bool operator < (const Node& t) const { 15 return t.cnt == cnt ? time < t.time: cnt < t.cnt; 16 } 17 }; 18 19 class LFUCache { 20 int time; 21 unordered_map<int, Node> key_value; 22 set<Node> s; 23 int capacity; 24 public: 25 LFUCache(int _capacity) { 26 key_value.clear(); 27 time = 0; 28 s.clear(); 29 capacity = _capacity; 30 } 31 32 int get(int key) { 33 if(capacity == 0) { 34 return -1; 35 } 36 37 auto it = key_value.find(key); 38 if(it == key_value.end()) { 39 return -1; 40 } 41 Node cache = key_value[key]; 42 s.erase(cache); 43 cache.cnt++; 44 cache.time = ++time; 45 s.insert(cache); 46 it->second = cache; 47 48 return cache.value; 49 } 50 51 void put(int key, int value) { 52 if(capacity == 0) { 53 return ; 54 } 55 56 auto it = key_value.find(key); 57 58 if(it == key_value.end()) { 59 if(key_value.size() == capacity) { 60 key_value.erase(s.begin()->key); 61 s.erase(s.begin()); 62 } 63 64 Node node = Node(1, ++time, key, value); 65 key_value.insert(make_pair(key, node)); 66 s.insert(node); 67 68 } 69 else { 70 Node tmp = key_value[key]; 71 s.erase(tmp); 72 tmp.cnt += 1; 73 tmp.time = ++time; 74 tmp.value = value; 75 it->second = tmp; 76 s.insert(tmp); 77 } 78 79 } 80 }; 81 82 /** 83 * Your LFUCache object will be instantiated and called as such: 84 * LFUCache* obj = new LFUCache(capacity); 85 * int param_1 = obj->get(key); 86 * obj->put(key,value); 87 */
方法二:
每一个频率创建一个链表,然后还有一个unordered_map用作定位
struct Node { int key; int val; int freq; Node(){} Node(int _key, int _val, int _freq) { key = _key; val = _val; freq = _freq; } }; class LFUCache { unordered_map<int, list<Node> > key_to_freq; unordered_map<int, list<Node>::iterator> key_to_value; int capacity; int minfreq; public: LFUCache(int _capacity) { capacity = _capacity; key_to_freq.clear(); key_to_value.clear(); minfreq = 0; } int get(int key) { if(capacity == 0) { return -1; } auto iter = key_to_value.find(key); if(iter == key_to_value.end()) { return -1; } else { list<Node>::iterator pos = iter->second; int freq = pos->freq, val = pos->val; key_to_freq[freq].erase(pos); if(key_to_freq[freq].size() == 0) { key_to_freq.erase(freq); if(freq == minfreq) { minfreq += 1; } } key_to_freq[freq + 1].push_front(Node(key, val, freq + 1)); key_to_value[key] = key_to_freq[freq + 1].begin(); return val; } } void put(int key, int value) { if(capacity == 0) { return ; } auto iter = key_to_value.find(key); if(iter != key_to_value.end()) { list<Node>::iterator pos = iter->second; int freq = pos->freq, val = pos->val; key_to_freq[freq].erase(pos); key_to_value.erase(key); if(key_to_freq[freq].size() == 0) { key_to_freq.erase(freq); if(freq == minfreq) { minfreq += 1; } } key_to_freq[freq + 1].push_front(Node(key, value, freq + 1)); key_to_value[key] = key_to_freq[freq + 1].begin(); return ; } else { if(key_to_value.size() == capacity) { Node pos = key_to_freq[minfreq].back(); int val = pos.val, freq = pos.freq; key_to_value.erase(pos.key); key_to_freq[minfreq].pop_back(); if(key_to_freq[minfreq].size() == 0) { key_to_freq.erase(minfreq); } } //Node node = new Node(key, value, 1); key_to_freq[1].push_front(Node(key, value, 1)); key_to_value[key] = key_to_freq[1].begin(); minfreq = 1; } return ; } }; /** * 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); */