LintCode 24: LFU Cache(系统设计经典题)

  1. LFU Cache
    中文English
    LFU (Least Frequently Used) is a famous cache eviction algorithm.
    For a cache with capacity k, if the cache is full and need to evict a key in it, the key with the lease frequently used will be kicked out.

Implement set and get method for LFU cache.

Example Input: LFUCache(3) set(2,2) set(1,1) get(2) get(1) get(2) set(3,3) set(4,4) get(3) get(2) get(1) get(4)

Output: 2 1 2 -1 2 1 4

解法1:3个hashMap。
注意:

  1. 只有当某个freq的set全空的时候我们才需要更新minFreq。
    if (minFreq == freq && freq2set[minFreq].size() == 0) minFreq++;
  2. unordered_map<int, std::set> freq2set; //(freq, set of keys)
    这里我用的set。**但要注意set里面的元素应该按其插入的时间顺序排序,如果删掉元素则删掉最早的那个。**所以我专门定义一个Node,并重载<操作符。

代码如下:

struct Node {
    int key;
    int timestamp;
    Node(int k, int t) : key(k), timestamp(t) {}
    bool operator < (Node & A) {
        return this->timestamp < A.timestamp;
    }
};

bool operator < (const Node & A, const Node & B) {
    return A.timestamp < B.timestamp;
}

class LFUCache {
public:
    /*
    * @param capacity: An integer
    */
    LFUCache(int capacity) : cap(capacity), minFreq(0) {
        freq2set[1] = std::set<Node>();
        timestamp = 0;
    }

    /*
     * @param key: An integer
     * @param value: An integer
     * @return: nothing
     */
    void set(int key, int value) {
        timestamp++;
        if (key2value.find(key) != key2value.end()) {
            key2value[key] = value;
            get(key);
            return;
        }
        
        if (key2value.size() >= cap) {
            //int lowestKey = *(freq2set[minFreq].begin());
            Node firstMinFreqNode = *(freq2set[minFreq].begin());
            freq2set[minFreq].erase(firstMinFreqNode);
            key2value.erase(firstMinFreqNode.key);
            key2freq.erase(firstMinFreqNode.key);
        }
        
        key2value[key] = value;
        minFreq = 1;
        key2freq[key] = 1;
        freq2set[1].insert(Node(key, timestamp));
    }

    /*
     * @param key: An integer
     * @return: An integer
     */
    int get(int key) {
        timestamp++;
        if (key2value.find(key) == key2value.end()) {
            return -1;
        }
        int freq = key2freq[key];
        
        for (auto s : freq2set[freq]) {
            if (s.key == key) freq2set[freq].erase(s);
        }
        
        
        //only when the last minFreq key was deleted, increment minFreq
        if (minFreq == freq && freq2set[minFreq].size() == 0) minFreq++;

        freq++;
        
        key2freq[key] = freq;
        if (freq2set.find(freq) == freq2set.end()) {
            freq2set[freq] = std::set<Node>();
        }
        freq2set[freq].insert(Node(key, timestamp));
        
        return key2value[key];
    }
    
private:
    unordered_map<int, int> key2value; //(key, value)
    unordered_map<int, int> key2freq; //(key, freq)
    unordered_map<int, std::set<Node>> freq2set; //(freq, set of keys)
    
    int cap;
    int minFreq;
    int timestamp;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值