LFU

2020-06-08  本文已影响0人  GOGOYAO

参考

LeetCode算法题解:LFU Cache
LFU Cache 最近最不常用页面置换缓存器

题目要求

设计并实现一个数据结构,满足LFU (Least Frequently Used) Cache特性,实现两种操作:get和put

public class LFUCache {
    public LFUCache(int capacity) {}  
    public int get(int key) {}
    public void put(int key, int value) {}
}

要求O(1)的时间复杂度

思路一

O(1)的复杂度,第一想到的就是hash表。使用hash表可以O(1)时间内,获取到key-value。频次更新也可以用一个map,频次作为key,链表位置作为value,入链表的先后顺序和时间相关。

class LFUCache {
public:
    LFUCache(int capacity) {
        cap = capacity;
    }
    
    int get(int key) {
        if (m.count(key) == 0) return -1;
        freq[m[key].second].erase(iter[key]);
        ++m[key].second;
        freq[m[key].second].push_back(key);
        iter[key] = --freq[m[key].second].end();
        if (freq[minFreq].size() == 0) ++minFreq;
        return m[key].first;
    }
    
    void put(int key, int value) {
        if (cap <= 0) return;
        if (get(key) != -1) {
            m[key].first = value;
            return;
        }
        if (m.size() >= cap) {
            m.erase(freq[minFreq].front());
            iter.erase(freq[minFreq].front());
            freq[minFreq].pop_front();
        }
        m[key] = {value, 1};
        freq[1].push_back(key);
        iter[key] = --freq[1].end();
        minFreq = 1;
    }

private:
    int cap, minFreq;
    unordered_map<int, pair<int, int>> m;  // pair.first : value of data, pair.second : frequency
    unordered_map<int, list<int>> freq;  // list<int> : list for data keys, the key of map is frequency
    unordered_map<int, list<int>::iterator> iter;  // data key's position in the list, the key of map is key
};

思路二

思路一中,全部用hashmap来实现。但是没有必要使用那么多hashmap。因为频次的增加,都是+1,也就是说数据节点只需要往后移动一位,那么使用链表也可以管理频次,无序hashmap。相对而言,实现的代码会更复杂一些,但是可以减少hash的计算,理论上性能会更优。
具体可参见LeetCode算法题解:LFU Cache

上一篇下一篇

猜你喜欢

热点阅读