leedcode:LFU缓存

4.5日:LFU缓存

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

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

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

分析:HashMap<Integer, Node> cache 存缓存的内容; min 是最小访问频次; HashMap<Integer, LinkedHashSet> freqMap 存每个访问频次对应的Node的双向链表(直接用了JDK现有的LinkedHashSet,其实现了1条双向链表贯穿哈希表中的所有Entry,支持以插入的先后顺序对原本无序的HashSet进行迭代)

class LFUCache{
    //存储缓存内容
    Map<Integer,Node> cache;
    //存储每个频次对应的双向链表
    Map<Integer,LinkedHashSet<Node>> freqMap;
    int size;
    int capacity;
    //存储当前最小频次
    int min;
    
    public LFUCache(int capacity){
        cache = new HashMap<>(capacity);
        freMap = new HashMap<>();
        this.capacity = capacity;
    }
    
    public int get(int key){
        Node node = cache.get(key);
        if (node == null){
            return -1;
        }
        freqInc(node);
        return node.value;
    }
    
    public void put(int key,int value){
        if (capacity == 0){
            return;
        }
        Node node = cache.get(key);
        if (node != null){
            node.value = value;
            freqInc(node);
        }else{
            if (size == capacity){
                Node deadNode = removeNode();
                cache.remove(deadNode.key);
                size--;
            }
            Node newNode = new Node(key,value);
            cache.put(key,newNode);
            addNode(newNode);
            size++;
        }
    }
    
    void freqInc(Node node){
        //从原freq对应的链表里移除,并更新min
        int freq = node.freq;
        LinkedHashSet<Node> set = freqMap.get(freq);
        set.remove(node);
        if (freq == min && set.size() == 0){
            min = freq + 1;
        }
        //加入新freq对应的链表
        node.freq++;
        LinkedHashSet<Node> newSet = freqMap.get(freq + 1);
        if (newSet == null){
            newSet = new LinkedHashSet<>();
            freqMap.put(freq + 1,newSet);
        }
        set.add(node);
        min = 1;
    }
    
    Node removeNode(){
        LinkedHashSet<Node> set = freqMap.get(min);
        Node deadNode = set.iterator().next();
        set.remove(deadNode);
        return deadNode;
    }
}

class Node{
    int key,value;
    int freq = 1;
    public Node(){}
    public Node(int key,int value){
        this.key = key;
        this.value = value;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值