1. 程式人生 > 實用技巧 >LeetCode460 LFU快取

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 */