LEETCODE 460 實現LFU緩存

leetcode 460
在這裏插入圖片描述
在這裏插入圖片描述
方法一:雙哈希表法
題目要求需要在常數時間完成插入和查找算法,聯繫之前的LRU算法,很容易想到用哈希表。具體做法如下:
第一個哈希表存儲 使用頻率freq一個雙向鏈表這樣一對映射,鏈表的每個節點存儲key valuefreq(使用頻率);
第二個哈希表存儲 freq鏈表中的一個節點這樣一對映射;
1.對於get()操作
首先根據key找到對應的鏈表節點,從而在第二個哈希表中找到value,freq,同時將該節點從當前鏈表刪除(如果刪除後爲空,可能需要更新最小freq).將freq+1,新建一個節點插入下一個鏈表中;
2.對於put()操作
如果key已經存在,那麼等同於get()操作,只需要另外將value更新就可以;

否則,判斷當前是否達到了最大容量限制,若沒有則只需要新建一個節點{freq=1,key,value},更新兩個哈希表和最小使用頻率即可;若達到了最大最大容量,找到最小使用頻率對應的節點,將其從兩個哈希表中刪除,同時可能需要更新最小使用頻率;

class LFUCache {
  public:  
    struct node
    {
        int key,val,freq;
        node(int k,int v,int f):key(k),val(v),freq(f){}     
    };
    
    unordered_map<int,list<node>>cache;//以頻率爲索引
    unordered_map<int,list<node>::iterator>sea;//以鍵值爲索引
    int sz;
    int minfreq;
public:
    LFUCache(int capacity) {
     sz=capacity;
     minfreq=0;
    }
    
    int get(int key) {
    if(sz==0||sea.find(key)==sea.end())return -1;
    auto it=sea[key];
    list<node>::iterator no=it;
    int f=no->freq,val=no->val;
    cache[f].erase(no);
    node n(key,val,f+1);
    cache[f+1].push_front(n);
    if(cache[f].size()==0)
    {
        cache.erase(f);
        if(minfreq==f)
            minfreq++;
    } 
    sea[key]=cache[f+1].begin();
    return val;
    }
    
    void put(int key, int value) {
    if(sz==0)return;
    if(sea.size()>0&&sea.find(key)!=sea.end())
    {
       get(key);
       sea[key]->val=value;   
     
    }
     else
    {
         
         if(sea.size()==sz)
         {
             auto no=cache[minfreq].back();
             int f=no.freq,val=no.val,k=no.key;
             
             cache[minfreq].pop_back();
             if(cache.count(minfreq)==0)
             {
                 minfreq+=1;
                 cache.erase(f);
             }
             sea.erase(k);         
         }
                 
        auto no=node(key,value,1);
        cache[1].push_front(no);
        minfreq=1;
        sea[key]=cache[1].begin();
    }
    }
   
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章