【数据结构】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);
 */
相关推荐
极光代码工作室25 分钟前
基于SpringBoot的流浪狗管理系统的设计与实现
java·spring boot·后端
毕设源码-朱学姐26 分钟前
【开题答辩全过程】以 基于JAVA的恒星酒店客房管理系统为例,包含答辩的问题和答案
java·开发语言
思密吗喽30 分钟前
景区行李寄存管理系统
java·开发语言·spring boot·毕业设计·课程设计
gladiator+1 小时前
Redis之BigKey的常见问题以及大厂相关面试题
java·数据库·redis
合方圆~小文1 小时前
AI摄像头精准识别技术依赖于深度算法
数据结构·数据库·数码相机·模块测试
tanxiaomi1 小时前
Redis相关面试题
数据库·redis·缓存
松涛和鸣1 小时前
16、C 语言高级指针与结构体
linux·c语言·开发语言·数据结构·git·算法
Controller-Inversion1 小时前
岛屿问题(dfs典型问题求解)
java·算法·深度优先
okseekw2 小时前
Java 字符串三巨头:String、StringBuilder、StringJoiner —— 初学者避坑指南 🤯
java
毕设源码余学姐2 小时前
计算机毕设 java 中医药药材分类采购网站 SSM 框架药材交易平台 Java 开发的分类采购与订单管理系统
java·开发语言·课程设计