LFU算法

LFU算法

Least Frequently Used(最不频繁使用)
在这里插入图片描述
Leetcode有原题,之前手写过LRU,数据结构还是习惯于用java实现,实现是copy的评论题解。
题解注释写的很清楚

大致就是说LFUCache类维护一个存放node的map,同时维护两个双向链表,注意这个双向链表里面又包含了两个双向链表,访问的频率是first最大,last最小。其余的就是正常的双向链表的操作了(插入,删除)

import java.util.HashMap;
import java.util.Map;class LFUCache {Map<Integer, Node> cache; // 存储缓存的内容,Node中除了value值外,还有key、freq、所在doublyLinkedList、所在doublyLinkedList中的postNode、所在doublyLinkedList中的preNode,具体定义在下方。DoublyLinkedList firstLinkedList; // firstLinkedList.post 是频次最大的双向链表DoublyLinkedList lastLinkedList; // lastLinkedList.pre 是频次最小的双向链表,满了之后删除 lastLinkedList.pre.tail.pre// 这个Node即为频次最小且访问最早的Nodeint size;int capacity;public LFUCache(int capacity) {cache = new HashMap<>(capacity);firstLinkedList = new DoublyLinkedList();lastLinkedList = new DoublyLinkedList();firstLinkedList.post = lastLinkedList;  // 是按照倒序排列的,最大的是firstlastLinkedList.pre = firstLinkedList;this.capacity = capacity;}public int get(int key) {Node node = cache.get(key);if (node == null) {return -1;}// 该key访问频次+1freqInc(node);return node.value;}public void put(int key, int value) {if (capacity == 0) {return;}Node node = cache.get(key);// 若key存在,则更新value,访问频次+1if (node != null) {node.value = value;freqInc(node);} else {// 若key不存在if (size == capacity) {// 如果缓存满了,删除lastLinkedList.pre这个链表(即表示最小频次的链表)中的tail.pre这个Node(即最小频次链表中最先访问的Node),如果该链表中的元素删空了,则删掉该链表。cache.remove(lastLinkedList.pre.tail.pre.key);lastLinkedList.removeNode(lastLinkedList.pre.tail.pre);size--;if (lastLinkedList.pre.head.post == lastLinkedList.pre.tail) {removeDoublyLinkedList(lastLinkedList.pre);}}// cache中put新Key-Node对儿,并将新node加入表示freq为1的DoublyLinkedList中,若不存在freq为1的DoublyLinkedList则新建。Node newNode = new Node(key, value);cache.put(key, newNode);if (lastLinkedList.pre.freq != 1) {DoublyLinkedList newDoublyLinedList = new DoublyLinkedList(1);addDoublyLinkedList(newDoublyLinedList, lastLinkedList.pre);newDoublyLinedList.addNode(newNode);} else {lastLinkedList.pre.addNode(newNode);}size++;}}/*** node的访问频次 + 1*/void freqInc(Node node) {// 将node从原freq对应的双向链表里移除, 如果链表空了则删除链表。DoublyLinkedList linkedList = node.doublyLinkedList;DoublyLinkedList preLinkedList = linkedList.pre;linkedList.removeNode(node);if (linkedList.head.post == linkedList.tail) {removeDoublyLinkedList(linkedList);}// 将node加入新freq对应的双向链表,若该链表不存在,则先创建该链表。node.freq++;if (preLinkedList.freq != node.freq) {DoublyLinkedList newDoublyLinedList = new DoublyLinkedList(node.freq);addDoublyLinkedList(newDoublyLinedList, preLinkedList);newDoublyLinedList.addNode(node);} else {preLinkedList.addNode(node);}}/*** 增加代表某1频次的双向链表*/void addDoublyLinkedList(DoublyLinkedList newDoublyLinedList, DoublyLinkedList preLinkedList) {newDoublyLinedList.post = preLinkedList.post;newDoublyLinedList.post.pre = newDoublyLinedList;newDoublyLinedList.pre = preLinkedList;preLinkedList.post = newDoublyLinedList;}/*** 删除代表某1频次的双向链表*/void removeDoublyLinkedList(DoublyLinkedList doublyLinkedList) {doublyLinkedList.pre.post = doublyLinkedList.post;doublyLinkedList.post.pre = doublyLinkedList.pre;}}class Node {int key;int value;int freq = 1;Node pre; // Node所在频次的双向链表的前继NodeNode post; // Node所在频次的双向链表的后继NodeDoublyLinkedList doublyLinkedList; // Node所在频次的双向链表public Node() {}public Node(int key, int value) {this.key = key;this.value = value;}}class DoublyLinkedList {int freq; // 该双向链表表示的频次DoublyLinkedList pre; // 该双向链表的前继链表(pre.freq < this.freq)DoublyLinkedList post; // 该双向链表的后继链表 (post.freq > this.freq)Node head; // 该双向链表的头节点,新节点从头部加入,表示最近访问Node tail; // 该双向链表的尾节点,删除节点从尾部删除,表示最久访问public DoublyLinkedList() {head = new Node();tail = new Node();head.post = tail;tail.pre = head;}public DoublyLinkedList(int freq) {head = new Node();tail = new Node();head.post = tail;tail.pre = head;this.freq = freq;}void removeNode(Node node) {node.pre.post = node.post;node.post.pre = node.pre;}void addNode(Node node) {node.post = head.post;head.post.pre = node;head.post = node;node.pre = head;node.doublyLinkedList = this;}}

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

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

相关文章

go语言入门介绍 - 特征、命名、关键字、保留字、声明

Go 语言是谷歌 2009 年首次推出并在 2012 年正式发布的一种全新的编程语言&#xff0c;可以在不损失应用程序性能的情况下降低代码的复杂性。 1、优点 自带gc。静态编译&#xff0c;编译好后&#xff0c;扔服务器直接运行。简单的思想&#xff0c;没有继承&#xff0c;多态&a…

基于springboot+vue的墙绘产品展示交易平台系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究背景…

「nuxt2配置tailwindcss」nuxt2添加tailwindcss详细步骤!解决版本不对称各种报错~~复制黏贴搞定!

运行环境 node和npm使用版本 node v14.21.3 (npm v6.14.18) 1.插件下载 官方文档说明 npm install -D nuxtjs/tailwindcss3.4.3 tailwindcss3.4.1 postcss^8.4.33 autoprefixer10.4.17 2.nuxt.config.js配置 module.exports {// ...buildModules: [nuxtjs/tailwindcss],// …

spring(1):基于XML获取Bean对象以及各种依赖注入方式

1. 获取Bean XML文件&#xff1a;<bean id"helloworld" class"org.kkk.spring6.bean.HelloWorld"></bean>1.1 根据id获取 Test public void testHelloWorld(){//加载XML文件ApplicationContext context new ClassPathXmlApplicationContext…

微信小程序商城注册是个人还是公司的?

随着移动互联网的飞速发展&#xff0c;微信小程序已经成为了商家们开展电子商务的重要平台之一。微信小程序商城以其便捷的操作、庞大的用户基础和较低的成本投入&#xff0c;吸引了众多商家的关注。然而&#xff0c;对于想要进入这一领域的创业者来说&#xff0c;一个基础性的…

C# CefSharp 输入内容,点击按钮,并且滑动。

前言 帮别人敲了个Demo,抱试一试心态&#xff0c;居然成功了&#xff0c;可以用。给小伙伴们看看效果。 遇到问题 1&#xff0c;input输入value失败&#xff0c;里面要套了个事件&#xff0c;再变换输入value。后来用浏览器开发工具&#xff0c;研究js代码&#xff0c;太难了&a…

Authorization Failed You can close this page and return to the IDE

一.问题描述 注册JetBrains成功&#xff0c;并且通过了学生认证&#xff0c;但在activate pycharm时&#xff0c;却显示Authorization Failed You can close this page and return to the IDE如上图 二.原因&#xff1a; 可能是因为之前使用了破解版pycharm 三.解决方法&am…

GNSS技术与无人机协同:开启未来交通新篇章

随着科技的不断发展&#xff0c;全球导航卫星系统&#xff08;GNSS&#xff09;技术与无人机技术的协同应用成为未来交通系统的引人瞩目的新方向。创新微公司在这一领域的技术创新为实现GNSS技术与无人机的紧密协同提供了新的可能性。本文将深入探讨GNSS技术与无人机协同的前景…

软件工程测试3

1.【多选】关于领域类建模说法正确的是 A. 需求描述中的名词或名词短语都划分为领域概念类 B. 在类的聚合关系中&#xff0c;聚合体对象是整体&#xff0c;聚合元素对象是部分 C. 需求描述中的名词、数词、形容词等有可能是属性值 D. 在类的继承关系中&#xff0c;父类中的属性…

创新医疗服务:宠物在线问诊系统的搭建与应用

随着科技的不断进步&#xff0c;创新的医疗服务方式也日渐成为宠物主人关心爱宠健康的首选。本文将深入介绍如何搭建一套创新的宠物在线问诊系统&#xff0c;并展示其应用的技术代码。 1. 系统架构与技术选择 在开始搭建之前&#xff0c;我们需要设计系统的架构并选择合适的…

springboot初始项目每一层的含义

一.创建的时候主要勾选了以下 二.项目架构 三.有的项目下创建出来&#xff0c;存在更多不同的层级 src/main/java/com/example/demo/controller: 控制器层&#xff0c;包含处理 HTTP 请求和响应的控制器类。 src/main/java/com/example/demo/service: 服务层&#xff0c;包含业…

ardupilot开发 --- RTSP多媒体数据流(视频流) 篇

0. 一些概念 RTSP是 TCP/IP 协议体系中的一个应用层协议&#xff0c;该协议定义了一对多应用程序如何有效地通过 IP 网络传送多媒体数据。RTSP在体系结构上位于RTP和RTCP之上&#xff0c;它使用TCP或UDP完成数据传输。 在mission planner中查看(拉取)RTSP视频流

我每天如何使用 ChatGPT

我们都清楚互联网的运作方式——充斥着各种“爆款观点”&#xff0c;极端分裂的意见&#xff0c;恶搞和无知现象屡见不鲜。 最近&#xff0c;大家对于人工智能&#xff08;AI&#xff09;特别是大语言模型&#xff08;LLMs&#xff09;和生成式 AI&#xff08;GenAI&#xff0…

四、arcgispro二次开发运行程序修改的地方还是没有变踩坑

对于arcgispro二次开发学习是一件充满兴趣并且具有好奇心的一件事&#xff0c;但是当创建了一个工程第一次调试成功&#xff0c;并出来了自己期待很久的一个程序后&#xff0c;当第二次修改并运行&#xff0c;发现一直没有反应&#xff0c;很是头疼&#xff0c;查了很多资料也没…

日常记帐软件,你的财务守护者

在快节奏的现代生活中&#xff0c;理财的重要性日益凸显。如何让每一分钱都花在刀刃上&#xff0c;是许多人都渴望知道的答案。今天&#xff0c;我要为大家介绍一款简单实用的记账软件——晨曦记账本&#xff0c;相信它会是你财务之路上的得力助手。 所需工具&#xff1a; 一…

Windows下网络编程(win32API+VS2022)

一、开发环境 我这里介绍下我用的环境安装过程。 所有版本的VS都可以的。 我当前环境是在Windows下&#xff0c;IDE用的是地表最强IDE VS2022。 下载地址&#xff1a;https://visualstudio.microsoft.com/zh-hans/downloads/ 因为我这里只需要用到C和C语言编程&#xff0c;那…

【Java万花筒】编程之术:掌握Java字节码操控的精髓

字节码探索手册&#xff1a;Java操纵库全方位解析* 前言 在Java开发领域&#xff0c;深入了解字节码是提升程序性能和灵活性的关键。本文将带领读者深入探索虚拟机与Java字节码操纵库&#xff0c;揭开这个引人入胜的编程领域的神秘面纱。从ASM、Byte Buddy、Javassist到cglib…

C++ STL之queue的使用及模拟实现

文章目录 1. 介绍2. 队列的使用3. 队列的模拟实现 1. 介绍 英文解释&#xff1a; 也就是说&#xff1a; 队列是一种容器适配器&#xff0c;专门用于在FIFO上下文(先进先出)中操作&#xff0c;其中从容器一端插入元素&#xff0c;另一端提取元素。 队列作为容器适配器实现&…

推荐系统——基于用户的协同过滤算法

1.RelateDTO package com.example.entity;/*** 协同过滤算法*/ public class RelateDTO {/** 用户id */private Integer useId;/** 商品id */private Integer goodsId;/** 指数 */private Integer index;public RelateDTO(Integer useId, Integer goodsId, Integer index) {th…

seldom之数据驱动

seldom之数据驱动 如果自动化某个功能&#xff0c;测试数据不一样而操作步骤是一样的&#xff0c;那么就可以使用参数化来节省测试代码。 seldom是我在维护一个Web UI自动化测试框&#xff0c;这里跟大家分享seldom参数化的实现。 GitHub&#xff1a;GitHub - SeldomQA/seld…