Skip to content

460. LFU 缓存

我的解题

#include <bits/stdc++.h>
using namespace std;

class Node
{
public:
    int key { 0 }, val { 0 }, freq { 1 };
    Node(int k, int v) :
                    key { k }, val { v }
    {

    }
    Node() = default;
};

class LFUCache
{
    unordered_map<int, list<Node*>> freq2node; // 根据频率快速地定位到节点,实现在O(1)内更新
    unordered_map<int, Node> key2node; // key node
    int capacity { 0 };
    int minFreq { 0 }; //最小频率,为了实现在O(1)内快速删除最小频率的节点
public:
    LFUCache(int capacity) :
                    capacity { capacity }
    {

    }
    /**
     *
     * @param key
     * @return
     */
    int get(int key)
    {
        if (capacity == 0)
        {
            return -1;
        }
        auto i = key2node.find(key);
        if (i != key2node.end()) // 存在
        {
            increaseFreq(i->second);
            return i->second.val;
        }
        else
        {
            return -1;
        }
    }
    /**
     *
     * @param key
     * @param value
     */
    void put(int key, int value)
    {
        if (capacity == 0)
        {
            return;
        }
        auto i = key2node.find(key);
        if (i == key2node.end()) // 不存在
        {
            if (key2node.size() == capacity)
            {
                removeMinFreqKey();
            }
            key2node[key] = Node { key, value };
            freq2node[1].push_front(&key2node[key]);
            minFreq = 1;
        }
        else // 存在
        {
            i->second.val = value;
            increaseFreq(i->second);
        }
    }
private:
    /**
     * @brief 增加节点的频率
     *
     * @param i
     */
    void increaseFreq(Node &n)
    {
        int freq = n.freq;
        int key = n.key;

        freq2node[freq].remove(&n);
        if (freq2node[freq].empty())
        {
            freq2node.erase(freq);
            if (minFreq == n.freq)
            {
                ++minFreq;
            }
        }
        ++n.freq;
        freq2node[n.freq].push_front(&n);
    }
    /**
     * @brief 淘汰掉最小频率的节点
     *
     */
    void removeMinFreqKey()
    {
        int key = freq2node[minFreq].back()->key;
        freq2node[minFreq].pop_back();
        if (freq2node[minFreq].empty())
        {
            freq2node.erase(minFreq);
        }

        key2node.erase(key);
    }
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache* obj = new LFUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */
// Driver code
int main()
{

    Solution solu;
    vector<int> nums = { 1, 3, 5, 4, 7 };
    return 0;
}
// g++ test.cpp --std=c++11 -pedantic -Wall -Wextra

官方解题

#include <bits/stdc++.h>
using namespace std;

// 缓存的节点信息
struct Node
{
    int key, val, freq;
    Node(int _key, int _val, int _freq) :
                    key(_key), val(_val), freq(_freq)
    {
    }
};
class LFUCache
{
    int minfreq, capacity;
    unordered_map<int, list<Node>::iterator> key_table;
    unordered_map<int, list<Node>> freq_table;
public:
    LFUCache(int _capacity)
    {
        minfreq = 0;
        capacity = _capacity;
        key_table.clear();
        freq_table.clear();
    }

    int get(int key)
    {
        if (capacity == 0)
            return -1;
        auto it = key_table.find(key);
        if (it == key_table.end())
            return -1;
        list<Node>::iterator node = it->second;
        int val = node->val, freq = node->freq;
        freq_table[freq].erase(node);
        // 如果当前链表为空,我们需要在哈希表中删除,且更新minFreq
        if (freq_table[freq].size() == 0)
        {
            freq_table.erase(freq);
            if (minfreq == freq)
                minfreq += 1;
        }
        // 插入到 freq + 1 中
        freq_table[freq + 1].push_front(Node(key, val, freq + 1));
        key_table[key] = freq_table[freq + 1].begin();
        return val;
    }

    void put(int key, int value)
    {
        if (capacity == 0)
            return;
        auto it = key_table.find(key);
        if (it == key_table.end())
        {
            // 缓存已满,需要进行删除操作
            if (key_table.size() == capacity)
            {
                // 通过 minFreq 拿到 freq_table[minFreq] 链表的末尾节点
                auto it2 = freq_table[minfreq].back();
                key_table.erase(it2.key);
                freq_table[minfreq].pop_back();
                if (freq_table[minfreq].size() == 0)
                {
                    freq_table.erase(minfreq);
                }
            }
            freq_table[1].push_front(Node(key, value, 1));
            key_table[key] = freq_table[1].begin();
            minfreq = 1;
        }
        else
        {
            // 与 get 操作基本一致,除了需要更新缓存的值
            list<Node>::iterator node = it->second;
            int freq = node->freq;
            freq_table[freq].erase(node);
            if (freq_table[freq].size() == 0)
            {
                freq_table.erase(freq);
                if (minfreq == freq)
                    minfreq += 1;
            }
            freq_table[freq + 1].push_front(Node(key, value, freq + 1));
            key_table[key] = freq_table[freq + 1].begin();
        }
    }
};

/**
 * Your LFUCache object will be instantiated and called as such:
 * LFUCache* obj = new LFUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */
// Driver code
int main()
{

    Solution solu;
    vector<int> nums = { 1, 3, 5, 4, 7 };
    return 0;
}
// g++ test.cpp --std=c++11 -pedantic -Wall -Wextra