面试常考问题:LRU(最近最久未使用)缓存策略的代码实现

主要思路:

假设缓存有固定容量,在缓存头部的意味着是最近最久没使用的可以丢弃,在缓存尾部是刚刚使用过的

对于读取缓存:get操作 (有则读取,并将该内容放到缓存尾部,代表刚刚使用;无则返回固定的值)

对于写入缓存:put操作(有则更新,并将内容放到缓存尾部,代表刚刚使用;无则判断容量是否满,没满直接插入,满了就删除缓存头部再插入)

这里想要两者都是O(1)的时间复杂度,可以考虑通过

一个双向链表list和一个unordered_map以及一个最大容量max来实现

其中list存储键值对,unordered_map存储键及其对应的迭代器

class LRUCache {
public:
    LRUCache(int capacity) {
           max=capacity;
    }
    
    int get(int key) {
     if(re.find(key)==re.end())//没有则返回-1
           return -1;
    else  //有则返回,并且插入到链表尾部
    {
    
     lru.push_back({key, (*re[key]).second});//插入新的节点
     lru.erase(re[key]);//删去旧的节点
     re[key]=--lru.end();
     //cout<<*re[key];
     return (*re[key]).second;
    }

    }
    
    void put(int key, int value) {
      
            if(re.find(key)==re.end())//没有则
                {
                                if(lru.size()>=max)//map和list中都需要删除
                
                    {
                        re.erase(lru.front().first);
                        lru.pop_front();
                        
                    }  
                   lru.push_back({key,value});
                    re[key]=--lru.end();
                    
                  
                }
                else 
                {
                    lru.erase(re[key]);//删去旧的节点
                    lru.push_back({key,value});
                    re[key]=--lru.end();
                }
    }
private:
   int max=0; //最大容量
   list<pair<int,int> > lru;//按访问的时间顺序存储
   unordered_map<int, list<pair<int,int> >::iterator> re;//如果get则放到链表的末尾,put时判断容量,不够则删除链表的头部
   //本来计划记录每个节点使用的频率,但还需要排序,这不太现实
};

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

猜你喜欢

转载自blog.csdn.net/weixin_42067304/article/details/110743819