460. LFU缓存

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

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

进阶:
你是否可以在 O(1) 时间复杂度内执行两项操作?

示例:

LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // 返回 1
cache.put(3, 3);    // 去除 key 2
cache.get(2);       // 返回 -1 (未找到key 2)
cache.get(3);       // 返回 3
cache.put(4, 4);    // 去除 key 1
cache.get(1);       // 返回 -1 (未找到 key 1)
cache.get(3);       // 返回 3
cache.get(4);       // 返回 4

我的代码 284ms

/**
 * 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);
 */
struct node
{
    int x,y,z;//对于set x为key y为使用次数,z为最近使用时间,    对于map x为value y为使用次数,z为最近使用时间,
    node(){}
    node(int i,int j,int k){x=i;y=j;z=k;}
    friend bool operator<(const node &n1,const node &n2)
    {
        if(n1.y<n2.y) return true;
        else if(n1.y==n2.y&&n1.z<n2.z) return true;
        else if(n1.y==n2.y&&n1.z==n2.z&&n1.x<n2.x) return true;
        return false;
    }
};
class LFUCache {
public:
    int count,index,capa;
    set<node>s;
    unordered_map<int,node> m;
    LFUCache(int capacity) {
        capa=capacity;
        count=0;
        index=0;
    }
    void deal_same(unordered_map<int,node>::iterator &it1,int key,int value)
    {
            node n1(key,it1->second.y,it1->second.z);
            set<node>::iterator it2=s.find(n1);
            s.erase(it2);
            n1.y++;
            n1.z=index;
            s.insert(n1);
            it1->second.x=value;
            it1->second.y++;
            it1->second.z=index;
            index++;
    }
    int get(int key) {
        unordered_map<int,node>::iterator it1=m.find(key);
        if(it1==m.end()) return -1;
        else
        {
            deal_same(it1,key,it1->second.x);
            return it1->second.x;
        }
    }
    
    void put(int key, int value) {
        if(capa==0) return;
        unordered_map<int,node>::iterator it1=m.find(key);
        if(it1==m.end())
        {
            if(count==capa)
            {
                node n1=*s.begin();
                s.erase(s.begin());
                m.erase(n1.x);
                count--;
            }
            node n2(key,1,index);
            s.insert(n2);
            node n3(value,1,index);
            m[key]=n3;
            index++;
            count++;

        }
        else
            deal_same(it1,key,value);
    }
};

网上的代码 256ms

class LFUCache {
public:
    LFUCache(int capacity) {
        cap_ = capacity;
        min_freq_ = -1;
    }
    
    int get(int key) {
        if (values_.count(key) == 0) {
            return -1;
        }
        Node& node = values_[key];
        freq_list_[node.freq].erase(node.iter);
        ++ node.freq;
        freq_list_[node.freq].emplace_back(key);
        node.iter = -- freq_list_[node.freq].end();
        if (freq_list_[min_freq_].size() == 0) {
            ++min_freq_;
        }
        return node.value;
    }
    
    void put(int key, int value) {
        if (cap_ <= 0) {
            return;
        }
        if (get(key) != -1) {
            values_[key].value = value;
            return;
        }
        if (values_.size() >= cap_) {
            auto& list = freq_list_[min_freq_];
            int evicted_key = list.front();
            list.pop_front();
            values_.erase(evicted_key);
        }
        min_freq_ = 1;
        auto& list = freq_list_[min_freq_];
        list.emplace_back(key);
        values_[key] = {value, min_freq_, -- list.end()};
        
    }
private:
    int cap_;
    int min_freq_;
    struct Node {
        int value;
        int freq;
        list<int>::iterator iter;
    };
    unordered_map<int, Node> values_; // key - node
    unordered_map<int, list<int>> freq_list_; // freq list_keys
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值