【数据结构】460. LFU 缓存

460. LFU 缓存

解题思路

  • get操作 返回key对应的val 然后增加对应的freq
  • 插入操作 如果key已经存在 直接进行更新 如果不存在 但是容器已经满了 直接进行删除freq最小的Key 之后进行插入
java 复制代码
class LFUCache {
           // key到  val的映射   KV
        HashMap<Integer,Integer> keyToVal;

        // 从key到freq的映射  KF
        HashMap<Integer,Integer> keyToFreq;

        // 一个频率对应多个 key  舍弃最久未使用的  FK
        HashMap<Integer,LinkedHashSet<Integer>> freqToKeys;
        // 记录最小的频率
        int minFreq;

        // 记录LFU 缓存的最大容量
        int cap;

    public LFUCache(int capacity) {
        keyToVal = new HashMap<>();
        keyToFreq = new HashMap<>();
        freqToKeys = new HashMap<>();
        this.cap = capacity;
        this.minFreq = 0;
    }
    // 返回对应key的val  然后增加对应的freq
    public int get(int key) {

        if(!keyToVal.containsKey(key)){
            return -1;// 返回-1  说明没找到
        }

        // 增加key对应的freq + 1  因为查找操作一次
        increaseFreq(key);
        return keyToVal.get(key);// 找到val

    }

    public void put(int key, int value) {
        // 如果key 已经存在直接更新

        if(this.cap <= 0){
            return;
        }

        if(keyToFreq.containsKey(key)){
            // 修改val即可
            keyToVal.put(key,value);
            // 对应的freq加一
            increaseFreq(key);

            return;
        }


        // key 不存在  需要插入 如果容量没有满 直接插入  如果已满 直接删除 freq最小的key


        if(this.cap <= keyToVal.size()){
            removeMinFreqKey();// 删除freq最小的key
        }


        keyToVal.put(key,value);

        keyToFreq.put(key,1);

        // 插入KF 表  一种freq对应多种key
        freqToKeys.putIfAbsent(1,new LinkedHashSet<>());


        freqToKeys.get(1).add(key);// 获取频率  添加一种key

        // 插入新的key之后最小的freq肯定是1

        this.minFreq = 1;


    }


    private void removeMinFreqKey(){
        // freq最小的key列表  通过 FK
        LinkedHashSet<Integer> keyList = freqToKeys.get(this.minFreq);// 获取所有的key

        // 最先被插入的key就是该被淘汰的key
        int deleteKey = keyList.iterator().next();

        // 更新FK 
        keyList.remove(deleteKey);

        if(keyList.isEmpty()){
            // 如果key列表是空的  说明都没有了直接删除freq
            freqToKeys.remove(this.minFreq);
        }

        // 更新KV
        keyToVal.remove(deleteKey);

        // 更新KF
        keyToFreq.remove(deleteKey);

    }

    private void increaseFreq(int key){
        int freq = keyToFreq.get(key);

        // 更新 KF
        keyToFreq.put(key,freq + 1);

        // 更新FK

        // 将key 从freq对应的列表中删除
        freqToKeys.get(freq).remove(key);

        // 将key加入freq + 1 对应的列表
        freqToKeys.putIfAbsent(freq + 1,new LinkedHashSet<>());// 创建新的
        freqToKeys.get(freq + 1).add(key);

        // 如果对应的列表空
        if(freqToKeys.get(freq).isEmpty()){
            freqToKeys.remove(freq);
            if(freq == this.minFreq){
                this.minFreq++;
            }
        }
    }
}

/**
 * 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);
 */
相关推荐
zhanghe68721 分钟前
es的密码带有特殊字符,导出
java
pnoker33 分钟前
IoT DC3 概念解读:把设备抽象成一套语义模板——位号、指令、事件与面向智能体的设备建模
java·人工智能·物联网·iot·dc3
my_realmy34 分钟前
Java SE 基础学习笔记(一):面向对象、继承多态、抽象接口与异常(JDK 8)
java·多线程·并发··生产者消费者模式
天远数科1 小时前
风险治理实战:基于天远车信盟出险构建自动化理赔核保流水线
java·网络·人工智能·自动化
骇客野人2 小时前
SpringBoot电商系统用户注册、登录、留存及数据埋点设计与落地实施方案
java·spring boot·后端
qiuhaipeng12 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库
wxwx_bscxy3222 小时前
基于Python新冠疫情可视化分析系统的设计与实现
java·数据库·spring boot·python·微信小程序·sqlite
evans在进步4 小时前
Tomcat NIO 工作原理详解:从 Acceptor、Poller 到容器处理链
java·tomcat·nio
明月_清风5 小时前
从二叉树到 B+ 树:一文搞懂工程中「树」的演化之道
数据结构·算法·go
渡我白衣5 小时前
并查集:基础认识与模拟实现
android·java·javascript·数据结构·c++·算法·并查集