【每日一题Day337】LC460LFU 缓存 | 双链表+哈希表
LFU 缓存【LC460】
请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。
实现
LFUCache类:
LFUCache(int capacity)- 用数据结构的容量capacity初始化对象int get(int key)- 如果键key存在于缓存中,则获取键的值,否则返回-1。void put(int key, int value)- 如果键key已存在,则变更其值;如果键不存在,请插入键值对。当缓存达到其容量capacity时,则应该在插入新项之前,移除最不经常使用的项。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近最久未使用 的键。为了确定最不常使用的键,可以为缓存中的每个键维护一个 使用计数器 。使用计数最小的键是最久未使用的键。
当一个键首次插入到缓存中时,它的使用计数器被设置为
1(由于 put 操作)。对缓存中的键执行get或put操作,使用计数器的值将会递增。函数
get和put必须以O(1)的平均时间复杂度运行。
-
错误答案
class LFUCache {// 注意:PriorityQueue要插入(删除)数据,顺序会发生改变,如果仅仅是修改已经稳定队列的值或内容,而不进行插入或者删除,那么,这个顺序是不会变的。// 使用Node存储每个key对应的value,以及该key的操作次数、最近操作时间// 小顶堆存储每个元素, 以使用次数及最近使用时间降序排序int capacity;PriorityQueue<Node> pq;Map<Integer, Node> map;int time;public LFUCache(int capacity) {this.capacity = capacity;this.pq = new PriorityQueue<>((o1, o2) -> o1.freq == o2.freq ? o1.time - o2.time : o1.freq - o2.freq);this.map = new HashMap<>();this.time = 0;}public int get(int key) {if (!map.containsKey(key)) return -1;Node node = map.get(key);node.freq += 1;node.time = time++;return node.val;}public void put(int key, int value) {if (map.containsKey(key)){Node node = map.get(key);node.val = value;node.freq += 1;node.time = time++;}else{Node node = new Node(key, value, time++, 1);if (pq.size() == capacity){Node node1 = pq.poll();map.remove(node1.key);}pq.add(node);map.put(key, node);}} } class Node{int key;int val;int time;int freq;public Node(){this.freq = 0;}public Node(int key, int val, int time, int freq){this.key = key;this.val = val;this.time = time;this.freq = freq;} }/*** 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);*/ -
思路
- LFU和LRU不同之处
- LRU移除元素时移除最近最久未使用的元素
- LFU移除元素时移除使用频率最少的最近最久未使用的元素
- 因此LFU实现可以仿照LRU,使用哈希表记录每个频率下的节点,相同频率下的各个节点以双向链表的形式组织
- 每次移除元素时移除频率最小的最久未使用的元素
- 每操作一次元素需要修改节点频率至相应链表
- 链表的首部存放最新操作的元素
- 为了快速找到某个节点在链表中的位置,可以使用哈希表存储每个key对应的节点
- 为了快速找到最小频率,维护一个int变量记录最小频率
- LFU和LRU不同之处
-
实现
class LFUCache {private static class Node {int key, value, freq = 1; // 新书只读了一次Node prev, next;Node(int key, int value) {this.key = key;this.value = value;}}private final int capacity;private final Map<Integer, Node> keyToNode = new HashMap<>();private final Map<Integer, Node> freqToDummy = new HashMap<>();private int minFreq;public LFUCache(int capacity) {this.capacity = capacity;}public int get(int key) {Node node = getNode(key);return node != null ? node.value : -1;}public void put(int key, int value) {Node node = getNode(key);if (node != null) { // 有这本书node.value = value; // 更新 valuereturn;}if (keyToNode.size() == capacity) { // 书太多了Node dummy = freqToDummy.get(minFreq);Node backNode = dummy.prev; // 最左边那摞书的最下面的书keyToNode.remove(backNode.key);remove(backNode); // 移除if (dummy.prev == dummy) { // 这摞书是空的freqToDummy.remove(minFreq); // 移除空链表}}node = new Node(key, value); // 新书keyToNode.put(key, node);pushFront(1, node); // 放在「看过 1 次」的最上面minFreq = 1;}private Node getNode(int key) {if (!keyToNode.containsKey(key)) { // 没有这本书return null;}Node node = keyToNode.get(key); // 有这本书remove(node); // 把这本书抽出来Node dummy = freqToDummy.get(node.freq);if (dummy.prev == dummy) { // 抽出来后,这摞书是空的freqToDummy.remove(node.freq); // 移除空链表if (minFreq == node.freq) { // 这摞书是最左边的minFreq++;}}pushFront(++node.freq, node); // 放在右边这摞书的最上面return node;}// 创建一个新的双向链表private Node newList() {Node dummy = new Node(0, 0); // 哨兵节点dummy.prev = dummy;dummy.next = dummy;return dummy;}// 在链表头添加一个节点(把一本书放在最上面)private void pushFront(int freq, Node x) {Node dummy = freqToDummy.computeIfAbsent(freq, k -> newList());x.prev = dummy;x.next = dummy.next;x.prev.next = x;x.next.prev = x;}// 删除一个节点(抽出一本书)private void remove(Node x) {x.prev.next = x.next;x.next.prev = x.prev;} }
相关文章:
【每日一题Day337】LC460LFU 缓存 | 双链表+哈希表
LFU 缓存【LC460】 请你为 最不经常使用(LFU)缓存算法设计并实现数据结构。 实现 LFUCache 类: LFUCache(int capacity) - 用数据结构的容量 capacity 初始化对象int get(int key) - 如果键 key 存在于缓存中,则获取键的值&#x…...
解决老版本Oracle VirtualBox 此应用无法在此设备上运行问题
问题现象 安装华为eNSP模拟器的时候,对应的Oracle VirtualBox-5.2.26安装的时候提示兼容性问题,无法进行安装,具体版本信息如下: 软件对应版本备注Windows 11专业工作站版22H222621eNSP1.3.00.100 V100R003C00 SPC100终结正式版…...
法规标准-UN R48标准解读
UN R48是做什么的? UN R48全名为关于安装照明和灯光标志装置的车辆认证的统一规定,主要描述了对各类灯具的布置要求及性能要求;其中涉及自动驾驶功能的仅有6.25章节【后方碰撞预警信号】,因此本文仅对此章节进行解读 功能要求 …...
自动化和数字化在 ERP 系统中意味着什么?
毋庸置疑,ERP系统的作用是让工作更轻松。它可以集成流程,提供关键分析,确保你的企业高效运营。这些信息可以提高你的运营效率,并将有限的人力资本重新部署到更有效、更重要的需求上。事实上,自动化和数字化是ERP系统最…...
python nvidia 显卡信息 格式数据
python nvidia 显卡信息 格式数据. def get_gpu_memory():result subprocess.check_output([nvidia-smi, --query-gpupci.bus_id,memory.used,memory.total,memory.free, --formatcsv])# 返回 GPU 的显存使用情况,单位为 Minfo []for t in csv.DictReader(result…...
LeetCode每日一题:1993. 树上的操作(2023.9.23 C++)
目录 1993. 树上的操作 题目描述: 实现代码与解析: 模拟 dfs 原理思路: 1993. 树上的操作 题目描述: 给你一棵 n 个节点的树,编号从 0 到 n - 1 ,以父节点数组 parent 的形式给出,其中 p…...
绿色计算产业发展白皮书:2022年OceanBase助力蚂蚁集团减排4392tCO2e
9 月 15 日,绿色计算产业联盟在 2023 世界计算大会期间重磅发布了《绿色计算产业发展白皮书(2023 版)》。蚂蚁集团作为指导单位之一,联合参与了该白皮书的撰写。 白皮书中指出,落实“双碳”战略,绿色计算已…...
阿里云通义千问14B模型开源!性能超越Llama2等同等尺寸模型
9月25日,阿里云开源通义千问140亿参数模型Qwen-14B及其对话模型Qwen-14B-Chat,免费可商用。Qwen-14B在多个权威评测中超越同等规模模型,部分指标甚至接近Llama2-70B。阿里云此前开源了70亿参数模型Qwen-7B等,一个多月下载量破100万࿰…...
两横一纵 | 寅家科技发布10年新征程战略
2023年9月22日,寅家科技“寅路向前”10年新征程战略发布会在上海举办,来自投资领域的东方富海、深创投、高新投等知名投资机构,一汽大众、一汽红旗、奇瑞汽车等主机厂,国家新能源汽车技术创新中心、梅克朗、芯驰科技、思特威等合作…...
二值贝叶斯滤波计算4d毫米波聚类目标动静属性
机器人学中有些问题是二值问题,对于这种二值问题的概率评估问题可以用二值贝叶斯滤波器binary Bayes filter来解决的。比如机器人前方有一个门,机器人想判断这个门是开是关。这个二值状态是固定的,并不会随着测量数据变量的改变而改变。就像门…...
【刷题笔记9.25】LeetCode:相交链表
LeetCode:相交链表 一、题目描述 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 二、分析及代码 方法一:使用哈希Set集合 (注意…...
打造本地紧密链接的开源社区——KCC@长沙开源读书会openKylin爱好者沙龙圆满举办...
2023年9月9日,由开源社联合 openKylin 社区举办的 KCC长沙开源读书会&openKylin 爱好者沙龙,在长沙圆满举办。这是 KCC长沙首次正式进入公众视野,开展开源交流活动,也是 openKylin 社区长沙首场线下沙龙。长沙地区及其周边的众…...
Python 笔记03(多线程)
一 打开命令行,查看本机IP windows r 命令行输入:cmd ipconfig 然后查看IPv4的地址:192.168.1*6.1 ipconfig 二 函数式多进程 from multiprocessing import Process import os, timedef func(name):print(进程的ID:, os.g…...
mysql-4:SQL的解析顺序
SQL语句的解析顺序 文章目录 SQL语句的解析顺序编写顺序与解析顺序解析顺序关键字FROMONOUTER JOINWHEREGROUP BYHAVINGSELECTDISTINCTORDER BYLIMIT 解析流程流程分析流程说明WHERE条件解析顺序 编写顺序与解析顺序 编写顺序 SELECT DISTINCT < select_list > FROM &l…...
如何通过优化Read-Retry机制降低SSD读延迟?
近日,小编发现发表于2021论文中,有关于优化Read-Retry机制降低SSD读延迟的研究,小编这里给大家分享一下这篇论文的核心的思路,感兴趣的同学可以,可以在【存储随笔】VX公号后台回复“Optimizing Read-Retry”获取下载链接。 本文中主要基于Charge Trap NAND架构分析。NAND基…...
matlab自动生成FPGA rom源码
1 matlab 源码 close all clear all clci=0:1:(300000-100-1); x=300000./(100+i); x=x./2; x=round(...
消息队列(RabbitMQ+RocketMQ+Kafka)
消息队列是一种应用程序之间通过异步通信进行数据交换的通信模式 消息队列的类型: 点对点,一对一的消息传递模型,其中每个消息只能被一个接收者消费。发送者将消息发送到队列中,而接收者从队列中获取消息并进行处理,…...
python判断语句
1.布尔类型 进行判断,只有是(True:本质上是一个数字,记作1)和否(False:本质上是一个数字,记作0)。 定义变量存储布尔类型数据: 变量名称 布尔类型字面量 a True代码演示: a True print(type(a))输出结…...
C# 虚方法
在C#中,虚方法(virtual methods)是一种允许派生类(子类)覆盖(重写)基类(父类)中的方法的技术。虚方法的定义和使用如下: 基类中定义虚方法: pub…...
微信小程序,动态设置三级联动, 省市区街道
1.第一步 传parentId0 查询省份 2.第二步 选择省份,传pathId选择省份的pathId, 不传parentId,会查询出 市/县数据 3.第三步 根据选择县的parentId 查询街道数据,传parentId选择的县id 4.选择结果回显 显示所选择的 path 以/分割 取最后一级<van-dropdown-menu…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
