LeetCode460 LFU缓存
请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。它应该支持以下操作:get 和 put。
get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。
put(key, value) - 如果键已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除最久未使用的键。
「项的使用次数」就是自插入该项以来对其调用 get 和 put 函数的次数之和。使用次数会在对应项被移除后置为 0 。
这题和LRU类似,但是多了一个使用频率的问题。可以通过相同的思路,但是增加一个哈希表的方式来解决。但是也可以直接依靠set的自动排序特点来解决。
关于如何给set或者map设置比较函数,来给自己定义的结构类型排序,可以参考这篇文章:https://blog.csdn.net/weixin_40237626/article/details/80511572
总之用一个哈希表来存储key对应的结构体,再把这些结构体插入到set中。根据set的自动排序特征就可以实现在o(1)时间内找到应该删除的元素。
1 struct Node{ 2 int key; 3 int value; 4 int latest_time; 5 int frequecy; 6 Node(int _key, int _value, int _latest_time, int _frequency):key(_key),value(_value),latest_time(_latest_time),frequecy(_frequency){ 7 } 8 bool operator< (const Node& comp) const{ 9 return frequecy==comp.frequecy?latest_time<comp.latest_time:frequecy<comp.frequecy; 10 } 11 12 }; 13 14 class LFUCache { 15 private: 16 int capacity; 17 int cur_time; 18 unordered_map<int,Node> key_table; 19 set<Node> sNode; 20 public: 21 LFUCache(int _capacity) { 22 capacity=_capacity; 23 cur_time=0; 24 key_table.clear(); 25 sNode.clear(); 26 } 27 28 int get(int key) { 29 if(capacity==0) 30 return -1; 31 auto it=key_table.find(key); 32 if(it==key_table.end()) 33 return -1; 34 Node cache=it->second; 35 sNode.erase(cache); 36 ++cache.frequecy; 37 cache.latest_time=++cur_time; 38 sNode.insert(cache); 39 it->second=cache; 40 return cache.value; 41 42 } 43 44 void put(int key, int value) { 45 if(capacity==0) 46 return; 47 auto it=key_table.find(key); 48 if(it!=key_table.end()){ 49 Node cache=it->second; 50 sNode.erase(cache); 51 ++cache.frequecy; 52 cache.value=value; 53 cache.latest_time=++cur_time; 54 sNode.insert(cache); 55 it->second=cache; 56 } 57 else{ 58 if(key_table.size()==capacity){ 59 key_table.erase(sNode.begin()->key); 60 sNode.erase(sNode.begin()); 61 } 62 Node cache=Node(key,value,++cur_time,1); 63 sNode.insert(cache); 64 key_table.insert(make_pair(key,cache)); 65 } 66 } 67 }; 68 69 /** 70 * Your LFUCache object will be instantiated and called as such: 71 * LFUCache* obj = new LFUCache(capacity); 72 * int param_1 = obj->get(key); 73 * obj->put(key,value); 74 */