LFU缓存(Leetcode460)

news2025/5/22 22:29:31
例题:

分析:

这道题可以用两个哈希表来实现,一个hash表(kvMap)用来存储节点,另一个hash表(freqMap)用来存储双向链表,链表的头节点代表最近使用的元素,离头节点越远的节点代表最近最少使用的节点。

注意:freqMap 的 key 为节点的使用频次。

下图是freqMap的结构:

这是kvMap: 它的key没有什么特殊含义,value是储存的节点

题目中调用get方法会增加元素的使用次数(freq),这时在freqMap中需要将该节点转移到对应的位置上(比如该节点使用了两次,那就把该节点转移到key为2的位置上去)

put方法分为两种情况:如果要添加的key不存在,说明是新元素,放到key为1的位置上,如果key存在,此时是修改操作,改变元素的value值,对应的频次+1,同样放到对应的位置上。

淘汰策略:要保证两个hash表中的节点数一致。

代码实现:
package leetcode;

import java.util.HashMap;

//设计LFU缓存
public class LFUCacheLeetcode460 {

    static class LFUCache {

        static class Node{
            Node prev;
            Node next;
            int key;
            int value;
            int freq = 1;
            public Node(){

            }
            public Node(int key, int value) {
                this.key = key;
                this.value = value;
            }
        }

        static class DoublyLinkedList{
            Node head;
            Node tail;
            int size;

            public DoublyLinkedList(){
                head = tail = new Node();
                head.next = tail;
                tail.prev = head;
            }

            //头部添加   head<->1<->2<->tail  添加3
            public void addFirst(Node node){
                Node oldFirst = head.next;
                oldFirst.prev = node;
                head.next = node;
                node.prev = head;
                node.next = oldFirst;
                size++;
            }

            //指定节点删除   head<->1<->2<->3<->tail  删除2
            public void remove(Node node){
                Node prev = node.prev;
                Node next = node.next;
                prev.next = next;
                next.prev = prev;
                size--;
            }

            //删除最后一个节点
            public Node removeLast(){
                Node last = tail.prev;
                remove(last);
                return last;
            }

            //判断双向链表是否为空
            public boolean isEmpty(){
                return size == 0;
            }
        }

        private HashMap<Integer,Node> kvMap = new HashMap<>();
        private HashMap<Integer,DoublyLinkedList> freqMap = new HashMap<>();
        private int capacity;
        private int minFreq = 1;
        public LFUCache(int capacity) {
            this.capacity = capacity;
        }

        /*
        * 获取节点  不存在:返回 -1
        *           存在: 增加节点的使用频次,将其转移到频次+1的链表中
        *           判断旧节点所在的链表是否为空,更新最小频次minFreq
        * */
        public int get(int key) {
            if(!kvMap.containsKey(key)){
                return -1;
            }
            Node node = kvMap.get(key);
            //先删除旧节点
            DoublyLinkedList list = freqMap.get(node.freq);
            list.remove(node);
            //判断当前链表是否为空,为空可能需要更新最小频次
            if(list.isEmpty() && node.freq == minFreq){
                minFreq++;
            }
            node.freq++;
            //将新节点放入新位置,可能该频次对应的链表不存在,不存在需要创建
            freqMap.computeIfAbsent(node.freq, k -> new DoublyLinkedList())
                    .addFirst(node);
            return node.value;
        }

        /*
        * 更新
        *     将节点的value更新,增加节点的使用频次,将其转移到频次+1的链表中
        * 新增
        *     检查是否超过容量,若超过,淘汰minFreq链表的最后节点
        *     创建新节点,放入kvMap,并加入频次为 1 的双向链表
        * */
        public void put(int key, int value) {
            if(kvMap.containsKey(key)){ //更新
                Node node = kvMap.get(key);
                DoublyLinkedList list = freqMap.get(node.freq);
                list.remove(node);
                if(list.isEmpty() && node.freq == minFreq){
                    minFreq++;
                }
                node.freq++;
                freqMap.computeIfAbsent(node.freq, k -> new DoublyLinkedList())
                        .addFirst(node);
                node.value = value;
            }else{ //新增
                //先判断容量是否已满
                if(kvMap.size() == capacity){
                    //执行淘汰策略
                    Node node = freqMap.get(minFreq).removeLast();
                    kvMap.remove(node.key);
                }
                Node node = new Node(key, value);
                kvMap.put(key, node);
                //加入频次为1的双向链表
                freqMap.computeIfAbsent(1, k -> new DoublyLinkedList())
                        .addFirst(node);
                minFreq = 1;
            }
        }
    }

    public static void main(String[] args) {
        LFUCache cache = new LFUCache(2);
        cache.put(1, 1);
        cache.put(2, 2);
        System.out.println(cache.get(1)); // 1 freq=2
        cache.put(3, 3);
        System.out.println(cache.get(2)); // -1
        System.out.println(cache.get(3)); // 3 freq=2
        cache.put(4, 4);
        System.out.println(cache.get(1)); // -1
        System.out.println(cache.get(3)); // 3  freq=3
        System.out.println(cache.get(4)); // 4  freq=2

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1434215.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot注解--02---常用注解汇总

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.SpringBoot 配置启动注解SpringBootApplication 2.Bean处理注解2.1 依赖注入AutoWired、Qualifier、Resource 2.2 类被 Spring 容器创建&#xff0c;管理 iocComp…

基于ESP8266 开发板(MCU)遥控小车

遥控小车 ​ 遥控界面 ​ 【项目源码】 第一版ESP8266 https://github.com/liyinchigithub/esp8266_car_webServerhttps://github.com/liyinchigithub/esp8266_car_webServer 第二版ESP32 GitHub - liyinchigithub/esp32-wroom-car: 嵌入式单片机 ESP32 Arduino 遥控小车&a…

第16届大广赛命题详情它来啦!

“中国大学生创造力”全国大学生广告艺术竞赛&#xff08;以下简称&#xff1a;广播竞赛&#xff09;作为高水平三维生产教育一体化、科学教育一体化竞争平台&#xff0c;坚持高地位&#xff0c;基于大模式&#xff0c;在19年的发展过程中&#xff0c;坚持道德培养人才的基础&a…

MySQL温故篇(一)SQL语句基础

一、SQL语句基础 1、SQL语言分类 DDL&#xff1a;数据定义语言 DCL&#xff1a;数据控制语言 DML&#xff1a;数据操作语言 DQL&#xff1a;数据的查询语言 2、数据类型 3、字符类型 char(11) &#xff1a; 定长 的字符串类型,在存储字符串时&#xff0c;最大字符长度11个&a…

TypeError: wave.ensureState is not a function 水球图引入报错问题

TypeError: wave.ensureState is not a function 水球图引入报错问题 什么问题&#xff1f; 版本问题 echarts4.x 版本 适用于 echarts-liquidfill2.x.x版本 echarts5.x 版本 适用于 echarts-liquidfill3.x.x版本 完美解决

使用PDFBox实现pdf转其他图片格式

最近在做一个小项目&#xff0c;项目中有一个功能要把pdf格式的图片转换为其它格式&#xff0c;接下来看看用pdfbox来如何实现吧。 首先导入pdfbox相关依赖&#xff1a; <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</a…

【FPGA】快速学习路径

FPGA学习教程、功利式学习路径、以找工作为目的&#xff0c;早日入门FPGA_哔哩哔哩_bilibili

解决git切换分支导致代码丢失的问题

问题描述&#xff1a; 最近写项目时&#xff0c;我在主分支&#xff08;master分支&#xff09;上面写的代码&#xff0c;但是我没有提交&#xff08;Commit&#xff09;到Git上。但是又碰到一个新的需求&#xff0c;所以需要去新建一个分支&#xff0c;当我切换到新建的分支&a…

【C语言初阶-const作用详解】const修饰变量、const修饰指针(图文详解版)

少年&#xff0c;做你认为对的事 目录 少年&#xff0c;做你认为对的事 1.const修饰变量 2.const修饰指针&#xff08;重要&#xff09; 代码1&#xff1a; 代码2&#xff1a; 代码3&#xff1a; ​编辑 3.结论 1.const修饰变量 const修饰变量将变量赋予了常量属性…

SpringBoot Security安全认证框架初始化流程认证流程之源码分析

SpringBoot Security安全认证框架初始化流程&认证流程之源码分析 以RuoYi-Vue前后端分离版本为例分析SpringBoot Security安全认证框架初始化流程&认证流程的源码分析 目录 SpringBoot Security安全认证框架初始化流程&认证流程之源码分析一、SpringBoot Security安…

(源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模

本篇文章是: 2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模的源码版本,包含具体建模代码到生成模型步骤。那么废话不多说直接开始展示建模过程建模: 数据预处理 之前我给大家提供的一年的风暴数据是远远不够的,要做时…

CentOS镜像如何下载?在VMware中如何安装?

一、问题 CentOS镜像如何下载&#xff1f;在VMware中如何安装&#xff1f; 二、解决 1、CentOS镜像的下载 &#xff08;1&#xff09;官方网站 The CentOS Project &#xff08;2&#xff09;官方中文官网 CentOS 中文 官网 &#xff08;3&#xff09;选择CentOS Linux…

机器学习数据预处理方法(基本信息探索)##1

文章目录 基于Kaggle电信用户流失案例数据&#xff08;可在官网进行下载&#xff09;数据解读与数据预处理数据质量探索变量相关性探索分析 基于Kaggle电信用户流失案例数据&#xff08;可在官网进行下载&#xff09; 数据解读与数据预处理 建议使用jupyter lab进行运行 imp…

新书速览|PyTorch 2.0深度学习从零开始学

实战中文情感分类、拼音汉字转化、中文文本分类、拼音汉字翻译、强化学习、语音唤醒、人脸识别 01 本书简介 本书以通俗易懂的方式介绍PyTorch深度学习基础理论&#xff0c;并以项目实战的形式详细介绍PyTorch框架的使用。为读者揭示PyTorch 2.0进行深度学习项目实战的核心技…

PPYOLE

1&#xff1a;参考GitHub - PaddlePaddle/PaddleDetection: Object Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection. 2&#xff1a;开源项目 - 飞…

CPU vs GPU:不仅仅是一字之差

当今科学技术的飞速发展&#xff0c;社会已经迈入了信息时代的智能化阶段。人脸识别、智能客服、个性化推荐等应用已经深入到日常生活的各个方面。这些看得见的应用背后&#xff0c;是看不见的算力在默默地支撑着。在满足这些高算力需求的过程中&#xff0c;CPU 和 GPU 作为计算…

【Leetcode】第 383 场周赛

文章目录 100214. 边界上的蚂蚁题目思路代码结果 100204. 将单词恢复初始状态所需的最短时间 I题目思路代码结果 100189. 找出网格的区域平均强度题目思路代码结果 100203. 将单词恢复初始状态所需的最短时间 II题目思路代码结果 100214. 边界上的蚂蚁 题目 题目链接 给你一个…

Java21 + SpringBoot3集成七牛云对象存储OSS,实现文件上传

文章目录 前言实现步骤引入maven依赖修改配置文件创建七牛云配置类创建文件操作服务类创建文件操作控制器前端实现运行效果 总结 前言 近日心血来潮想做一个开源项目&#xff0c;目标是做一款可以适配多端、功能完备的模板工程&#xff0c;包含后台管理系统和前台系统&#xf…

Unity3D实现项目限制功能(使用次数限制和时间限制)

系列文章目录 unity工具 文章目录 系列文章目录前言一、时间限制1-1、代码如下&#xff1a; 二、次数限制2-1、 在Unity项目中需要对注册表进行操作&#xff0c;还需要设置一下API兼容级别设置成 .NET Framework2-2、设置如下图 Player里面2-3、代码如下&#xff1a; 三、同时…

不负书香,传承有我

随着科技的飞速发展&#xff0c;电子书、网络资源日益丰富&#xff0c;但实体书仍以其独特的魅力和不可替代性在每个人的生活中占据一席之地。为确保每一本书都能被正确、有序地摆放&#xff0c;为每一个读者提供便利&#xff0c;在2024年1月24日&#xff0c;曲阜师范大学计算机…