[ Leetcode ] No.460 LFU缓存

题目:
请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。它应该支持以下操作:get 和 put。

get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。
put(key, value) - 如果键不存在,请设置或插入值。当缓存达到其容量时,则应该在插入新项之前,使最不经常使用的项无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近 最少使用的键。
「项的使用次数」就是自插入该项以来对其调用 get 和 put 函数的次数之和。使用次数会在对应项被移除后置为 0 。

题解:
这题其实不会做... 先记录 有机会重新写过

struct Node {
    int key, val, fre;
    Node(int x, int y, int z): key(x), val(y), fre(z) {}
};
class LFUCache {
public:
    int cap, minfreq;
    unordered_map<int, list<Node>::iterator> stuff;
    unordered_map<int, list<Node>> fre_table;

    LFUCache(int capacity) {
        cap = capacity;
        minfreq = 0;
        stuff.clear(); fre_table.clear();
    }
    
    int get(int key) {
        if(cap == 0) return -1;
        auto it = stuff.find(key);
        if (it == stuff.end()) return -1;
        // 有数值
        list<Node>::iterator node = it->second;
        int val = node->val, fre = node->fre;
        fre_table[fre].erase(node); //将该节点修改频率哈希表,应存入+1处
        if(fre_table[fre].size() == 0) {
            fre_table.erase(fre); //直接把链表删除
            if (minfreq == fre) minfreq += 1;
        }
        // 插入
        fre_table[fre + 1].push_front(Node(key, val, fre + 1));
        stuff[key] = fre_table[fre + 1].begin(); //新节点插入节点头
        return val;
    }
    
    void put(int key, int value) {
        if(cap == 0) return;
        auto it = stuff.find(key);
        if(it == stuff.end()) {
            if(stuff.size() == cap) { //缓存已满
                auto it2 = fre_table[minfreq].back(); //旧在末尾
                stuff.erase(it2.key);
                fre_table[minfreq].pop_back();
                if(fre_table[minfreq].size() == 0) fre_table.erase(minfreq);
            }
            fre_table[1].push_front(Node(key, value, 1));
            stuff[key] = fre_table[1].begin();
            minfreq = 1;
        } else {
            list<Node>::iterator node = it->second;
            int fre = node->fre;
            fre_table[fre].erase(node);
            if(fre_table[fre].size() == 0) {
                fre_table.erase(fre);
                if(minfreq == fre) minfreq += 1;
            }
            fre_table[fre + 1].push_front(Node(key, value, fre + 1));
            stuff[key] = fre_table[fre + 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);
 */
原文地址:https://www.cnblogs.com/recoverableTi/p/12641390.html