LRU & LFU Cache (Leetcode 146, Leetcode 460)

先來(lái)看LRU Cache,LRU Cache的重點(diǎn)就是建立一個(gè) map<key, list<>::iterator> 的hash table。key存需要找的key,value是list的iterator。

而這個(gè)list<pair<int, int>> 存的就是key value pair。在get或set時(shí),要把這個(gè)<key, value> pair 從當(dāng)前位置,放到棧頂。這個(gè)是用list.splice函數(shù)實(shí)現(xiàn)的。splice函數(shù)的用法如下:

list.splice(position, list name, list iterator)
lst.splice(lst.begin(), lst, it);

注意:在這里統(tǒng)一一下,無(wú)論LRU還是LFU Cache, 一律先刪,再加。

class LRUCache {
public:
    LRUCache(int capacity) {
        this->capacity = capacity;
    }
    
    int get(int key) {
        if(!mp.count(key)) return -1;
        auto it = mp[key];
        lst.splice(lst.begin(), lst, it);
        mp[key] = lst.begin();
        return it->second;
    }
    
    void put(int key, int value) {
        if(get(key) != -1){
            mp[key]->second = value;
        }
        else{
            if(lst.size() == capacity){
                auto it = lst.back();
                lst.pop_back();
                mp.erase(it.first);
            }
            lst.push_front({key, value});
            mp[key] = lst.begin();

        }
    }
private:
    int capacity;
    list<pair<int, int>> lst;
    unordered_map<int, list<pair<int, int>>::iterator> mp;
};

LFU Cache則要復(fù)雜不少,具體參考grandyang的LFU solution:
http://www.cnblogs.com/grandyang/p/6258459.html

LFU Cache的經(jīng)典solution是用doubly linkded list (http://dhruvbird.com/lfu.pdf),上文解法用三個(gè)Hashmap模擬了這個(gè)doubly linked list,非常巧妙. 另外trick是在set時(shí)調(diào)用get,并討論考慮get != -1的情況. 本文變化是當(dāng)capacity reach full時(shí),將隊(duì)尾pop出去. 注意,第一個(gè)keyValue Hashmap: key => {value, frequency}

純O(1)的solution:

class LFUCache {
public:
    LFUCache(int capacity) {
        cap = capacity;
    }
    
    int get(int key) {
        if(!keyValue.count(key)) return -1;
        auto it = locator[key];
        frequency[keyValue[key].second++].erase(it);
        frequency[keyValue[key].second].push_front(key);
        locator[key] = frequency[keyValue[key].second].begin();
        if(frequency[minFreq].empty()) minFreq++;
        return keyValue[key].first;
        
    }
    
    void put(int key, int value) {
        if(cap <= 0) return;
        if(get(key) != -1){
            keyValue[key].first = value;
        }else{
            if(keyValue.size() == cap){
                int temp = frequency[minFreq].back();
                frequency[minFreq].pop_back();
                locator.erase(temp);
                keyValue.erase(temp);
            }
            keyValue[key] = {value, 1};
            frequency[1].push_front(key);
            locator[key] = frequency[1].begin();
            minFreq = 1;
        }
    }
private:
    int cap, minFreq;
    unordered_map<int, pair<int, int>> keyValue;
    unordered_map<int, list<int>> frequency;
    unordered_map<int, list<int>::iterator> locator;
};

簡(jiǎn)單一點(diǎn)的solution,不O(1), 但是省掉了一個(gè)HashMap,直接用list.remove(key)

class LFUCache {
public:
    LFUCache(int capacity) {
        this->capacity = capacity;
    }
    
    int get(int key) {
        if(!keyValue.count(key)) return -1;
        frequency[keyValue[key].second++].remove(key);
        frequency[keyValue[key].second].push_front(key);
        if(frequency[minFreq].empty()) minFreq++;
        return keyValue[key].first;
    }
    
    void put(int key, int value) {
        if(capacity <= 0) return;
        if(get(key) != -1){
            keyValue[key].first = value;
        }
        else{
            if(keyValue.size() == capacity){
                int temp = frequency[minFreq].back();
                frequency[minFreq].pop_back();
                keyValue.erase(temp);
            }
            keyValue[key] = {value, 1};
            frequency[1].push_front(key);
            minFreq = 1;
        }
    }
private:
    int capacity, minFreq = 0;
    unordered_map<int, pair<int, int>> keyValue;
    unordered_map<int, list<int>> frequency;
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容