Leetcode典型題解答和分析、歸納和彙總——T146(LRU緩存機制)

問題描述:

運用你所掌握的數據結構,設計和實現一個  LRU (最近最少使用) 緩存機制。它應該支持以下操作: 獲取數據 get 和 寫入數據 put 。獲取數據 get(key) - 如果密鑰 (key) 存在於緩存中,則獲取密鑰的值(總是正數),否則返回 -1。寫入數據 put(key, value) - 如果密鑰不存在,則寫入其數據值。當緩存容量達到上限時,它應該在寫入新數據之前刪除最近最少使用的數據值,從而爲新的數據值留出空間。

問題分析:

首先,我們需要詳細解讀一下什麼是LRU算法(Least Recently Used):

其實這是一種緩存淘汰策略。因爲計算機的緩存容量有限,如果緩存滿了就要刪除一些內容,給新的內容騰出空間。但問題是刪除哪些內容呢?這裏給出的規則就是:保存最近使用的數據(表示有用),刪除長時間沒有使用過的數據。

明確了相關定義之後,我們來進行算法設計:

首先需要查找的複雜度爲常數級別的,而且要有順序,知道什麼是最近使用,什麼是最少使用的。

於是綜合上面的這些特點,我們使用hashmap 和鏈表這兩種數據結構相結合的模式。

class LRUCache {
    private:
    int cap;
    //雙鏈表:裝着(key,value)的元組
    list<pair<int,int>> cache;
    //哈希表:key映射到(key,value)在cache中的位置
    unordered_map<int, list<pair<int,int>>::iterator> map;

public:
    LRUCache(int capacity) {
             this->cap = capacity;
    }
    
    int get(int key) {
       auto it = map.find(key);
       //訪問的key不存在
       if(it==map.end()) return -1;
       //如果key存在,則把(key,value)放在隊頭
       pair<int,int> kv = *map[key];
       cache.erase(map[key]);
       cache.push_front(kv);
       //更新(key,value)在cache中的位置
       map[key] = cache.begin();
       return kv.second;
    }
    
    void put(int key, int value) {
       /* 要先判斷 key 是否已經存在 */ 
        auto it = map.find(key);
        if (it == map.end()) {
            /* key 不存在,判斷 cache 是否已滿 */ 
            if (cache.size() == cap) {
                // cache 已滿,刪除尾部的鍵值對騰位置
                // cache 和 map 中的數據都要刪除
                auto lastPair = cache.back();
                int lastKey = lastPair.first;
                map.erase(lastKey);
                cache.pop_back();
            }
            // cache 沒滿,可以直接添加
            cache.push_front(make_pair(key, value));
            map[key] = cache.begin();
        } else {
            /* key 存在,更改 value 並換到隊頭 */
            cache.erase(map[key]);
            cache.push_front(make_pair(key, value));
            map[key] = cache.begin();
        }
    }
};

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章