LRU緩存機制

LRU緩存機制

運用你所掌握的數據結構,設計和實現一個  LRU (最近最少使用) 緩存機制。它應該支持如下操做: 獲取數據 get 和 寫入數據 put 。緩存

獲取數據 get(key) - 若是密鑰 (key) 存在於緩存中,則獲取密鑰的值(老是正數),不然返回 -1。
寫入數據 put(key, value) - 若是密鑰不存在,則寫入其數據值。當緩存容量達到上限時,它應該在寫入新數據以前刪除最近最少使用的數據值,從而爲新的數據值留出空間。數據結構

進階:ide

你是否能夠在 O(1) 時間複雜度內完成這兩種操做?設計

示例:ci

LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );get

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 該操做會使得密鑰 2 做廢
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 該操做會使得密鑰 1 做廢
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4hash

思路:it

  只有鏈表才能夠實現插入和刪除操做在O(1)時間複雜度內完成,因此存儲內容要用鏈表實現class

  實現O(1)時間複雜度內訪問能夠用unordered_map和vector,可是vector不是關聯式容器,沒法進行key和list關聯,因此用unordered_map容器

class LRUCache {
private:
    int capacity;
    list<pair<int,int>> ls;//只有鏈表才能實現插入和刪除時間複雜度O(1)——實現存儲功能
    unordered_map<int,list<pair<int,int>>::iterator> hash;//哈希表實現,實現查找時間時間複雜度O(1)——實現查找功能
    //unordered_map中key爲key,value爲list的地址
public:
    LRUCache(int _capacity):capacity(_capacity){}
    
    int get(int key) 
    {
        if(hash.find(key)==hash.end())
            return -1;
        
        //訪問事後,要放到鏈表頭部
        int val=hash[key]->second;//取出list中的val
        ls.erase(hash[key]);//刪除鏈表中的源節點
        ls.push_front({key,val});//剛訪問過的要放到鏈表頭
        hash[key]=ls.begin();//更新hash表
        return val;
    }
    
    void put(int key, int value)
    {
        if(hash.find(key)!=hash.end())//在放入LRU前該值若存在,在hash和ls中刪除相應的記錄
        {
            ls.erase(hash[key]);
            hash.erase(key);
        }
        else if(hash.size()>=capacity)//若容量已經到達上限,在hash和ls中刪除最近最久沒有訪問的記錄
        {
            hash.erase(ls.back().first);
            ls.pop_back();
        }

        ls.push_front({key,value});
        hash[key]=ls.begin();

        return ;
    }
};

/**
 * 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);
 */
相關文章
相關標籤/搜索