LFU缓存(Leetcode460)

例题:

分析:

这道题可以用两个哈希表来实现,一个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  添加3public 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  删除2public 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=2cache.put(3, 3);System.out.println(cache.get(2)); // -1System.out.println(cache.get(3)); // 3 freq=2cache.put(4, 4);System.out.println(cache.get(1)); // -1System.out.println(cache.get(3)); // 3  freq=3System.out.println(cache.get(4)); // 4  freq=2}
}

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

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

相关文章

Deepin系统安装x11vnc远程桌面工具实现无公网ip访问本地桌面

文章目录 1. 安装x11vnc2. 本地远程连接测试3. Deepin安装Cpolar4. 配置公网远程地址5. 公网远程连接Deepin桌面6. 固定连接公网地址7. 固定公网地址连接测试 x11vnc是一种在Linux系统中实现远程桌面控制的工具&#xff0c;它的原理是通过X Window系统的协议来实现远程桌面的展…

Spring Boot整合MyBatis Plus实现基本CRUD与高级功能

文章目录 1. 引言2. 项目搭建与依赖配置2.1 添加MyBatis Plus依赖2.2 配置数据源与MyBatis Plus 3. 实现基本CRUD功能3.1 创建实体类3.2 创建Mapper接口3.3 实现Service层3.4 控制器实现 4. 高级功能实现4.1 自动填充功能4.2 乐观锁功能4.3 逻辑删除功能 5. 拓展&#xff1a;My…

构造回文数组

目录 原题描述&#xff1a; 题目描述 时间&#xff1a;1s 空间&#xff1a;256M 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 样例1输入&#xff1a; 样例1输出&#xff1a; 样例2输入&#xff1a; 样例2输出&#xff1a; 约定&#xff1a; 作…

ubantu扩容解决 sudo -i 报无法识别

GParted给ubuntu系统磁盘resize大小时候出现cannot resize read-only file system解决办法_gparted无法调整分区大小-CSDN博客https://blog.csdn.net/ningmengzhihe/article/details/127295333?spm1001.2014.3001.5506 解决磁盘挂载系统目录出现问题&#xff1a; 1、sudo -i…

【HarmonyOS应用开发】后台提醒(十六)

简述 随着生活节奏的加快&#xff0c;我们有时会忘记一些重要的事情或日子&#xff0c;所以提醒功能必不可少。应用可能需要在指定的时刻&#xff0c;向用户发送一些业务提醒通知。例如购物类应用&#xff0c;希望在指定时间点提醒用户有优惠活动。为满足此类业务诉求&#xf…

C语言-分支和循环语句

目录 分支语句 if语句 关系操作符&#xff1a; 逻辑操作符&#xff1a; switch语句 循环语句 while循环 for循环 ​编辑 循环控制语句&#xff08;break&#xff0c;continue&#xff09; goto语句充当循环 分支语句 if语句 if语句的括号内需要写条件表达式&#xff0c;通…

超多制作模板的姓氏头像生成器微信小程序源码

超多制作模板的姓氏头像生成器微信小程序源码&#xff0c;这是一款姓氏头像制作小工具&#xff0c;内含丰富多样的模板提供制作。 以前的基本是固定位置生成&#xff0c;这款制作支持拖拽调整位置&#xff0c;自定义颜色&#xff0c;阴影等等。

探索设计模式的魅力:外观模式简化术-隐藏复杂性,提供简洁接口的设计秘密

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 引言&#xff1a;探索简化之路 一、起源和演变 二、场景案例分析 2.1 不用模式实现&#xff1a;用一坨坨代码实现 2.2 问题 2.3 外观模式重构代码 定义 界面 接口 利用外观模式解决问题步骤 外观模式结构和说明 重构…

Linux 网络:PTP 简介

文章目录 1. 前言2. PTP(Precision Time Protocol​) IEEE 1588 协议简介2.1 PTP IEEE 1588 协议时间同步原理2.2 PTP IEEE 1588 协议时钟类型2.2.1 普通时钟(OC: Ordinary Clock)2.2.2 边界时钟(BC: Boundary Clock)2.2.3 透明时钟(TC: Transparent Clock)2.2.3.1 端对端透明时…

【论文研读】Better Together:Unifying Datalog and Equality Saturation

最近研究ReassociatePass整的头大&#xff0c;翻两篇Datalog的论文看看。 今天看的一篇是比较新的文章&#xff0c;23年4月贴到arxiv上的。 本文的主要贡献是提出了egglog,将Datalog和Eqsat结合起来&#xff0c;继承了Datalog的efficient incremental execution, cooperating a…

【前端web入门第四天】02 CSS三大特性+背景图

文章目录: 1. CSS三大特性 1.1继承性 1.2 层叠性 1.3 优先级 1.3.1 优先级1.3.2 优先级-叠加计算规则 2. 背景图 2.1 背景属性2.2 背景图2.3 背景图的平铺方式2.4 背景图位置2.5 背景图缩放2.6 背景图固定2.7 背景复合属性 1. CSS三大特性 1.1继承性 什么是继承性? 子级默…

前端实现搜索框筛选

效果图 页面解析 是一个input输入框和一个button按钮组成输入框查询 内容是一个折叠面板 html代码 <div class"left-content-box"><div class"colum-search"><el-input v-model"columKey" clearable placeholder"请输入关…

redis大数据统计之hyperloglog,GEO,Bitmap

目录 一、亿级系统常见的四中统计 1、聚合统计 2、排序统计 3、二值统计 4、基数统计 二、hyperloglog 去重的方式有哪些&#xff1f; hyperloglog实战演示 1、技术选型 2、代码演示 三、GEO GEO实战演示 四、Bitmap 一、亿级系统常见的四中统计 1、聚合统计 聚…

STM32F407移植OpenHarmony笔记7

继上一篇笔记&#xff0c;成功启动了liteos_m内核&#xff0c;可以创建线程了&#xff0c;也能看到shell控制台了。 今天研究文件系统&#xff0c;让控制台相关文件命令如mkdir和ls能工作。 liteos_m内核支持fatfs和littlefs两个文件系统&#xff0c; fatfs适用于SD卡&#xff…

将11.x.x升级至16.x.x不成功的一系列问题(二)node-sass sass-loader需安装指定版本

nvm 版本切换搞定了 咱就是说 那个node-sass好像有点毛病 还得指定对应的loaber版本 node.js 16.18.1对应的如下 “node-sass”: “^6.0.1”, “sass-loader”: “^10.0.1”, node.js 11.8.0 对应的如下 “node-sass”: “^4.14.1”, “sass-loader”: “^7.3.1”, 老项目即…

python-题库篇-数学

文章目录 求最大公约数和最小公倍数斐波那契数列求和运算求前n阶乘的和求年龄 求最大公约数和最小公倍数 两个数的最大公约数是两个数的公共因子中最大的那个数&#xff1b;两个数的最小公倍数 则是能够同时被两个数整除的最小的那个数。 输入&#xff1a;&#xff08;120 和…

零基础如何入门渗透测试2024年最新版,保姆级教程,小白必看!

转眼间&#xff0c;从大三开始学安全&#xff0c;到现在也有五年了&#xff0c;也算是对渗透测试有一定理解&#xff0c;今天也是出一篇入门教程&#xff0c;以实操为主&#xff0c;希望可以帮助到想入门渗透测试的小白。如果觉得有用&#xff0c;可以给我点个赞和收藏&#xf…

Android: 深入理解 ‘companion object {}‘

Android: 深入理解 ‘companion object {}’ Kotlin是一种现代的、静态类型的编程语言&#xff0c;它在设计时充分考虑了开发者的生产力和代码的可读性。其中一个独特的特性就是companion object。在本篇博客中&#xff0c;我们将深入探讨这个特性&#xff0c;理解它的工作原理…

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

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

EOF和0区别

题目描述 KiKi学习了循环&#xff0c;BoBo老师给他出了一系列打印图案的练习&#xff0c;该任务是打印用“*”组成的X形图案。 输入描述&#xff1a; 多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜…