leetcode 460. LFU 缓存

请你为 最不经常使用(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) 的平均时间复杂度运行。

示例:

输入:
[“LFUCache”, “put”, “put”, “get”, “put”, “get”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [3], [4, 4], [1], [3], [4]]
输出:
[null, null, null, 1, null, -1, 3, null, -1, 3, 4]

解释:
// cnt(x) = 键 x 的使用计数
// cache=[] 将显示最后一次使用的顺序(最左边的元素是最近的)
LFUCache lfu = new LFUCache(2);
lfu.put(1, 1); // cache=[1,_], cnt(1)=1
lfu.put(2, 2); // cache=[2,1], cnt(2)=1, cnt(1)=1
lfu.get(1); // 返回 1
// cache=[1,2], cnt(2)=1, cnt(1)=2
lfu.put(3, 3); // 去除键 2 ,因为 cnt(2)=1 ,使用计数最小
// cache=[3,1], cnt(3)=1, cnt(1)=2
lfu.get(2); // 返回 -1(未找到)
lfu.get(3); // 返回 3
// cache=[3,1], cnt(3)=2, cnt(1)=2
lfu.put(4, 4); // 去除键 1 ,1 和 3 的 cnt 相同,但 1 最久未使用
// cache=[4,3], cnt(4)=1, cnt(3)=2
lfu.get(1); // 返回 -1(未找到)
lfu.get(3); // 返回 3
// cache=[3,4], cnt(4)=1, cnt(3)=3
lfu.get(4); // 返回 4
// cache=[3,4], cnt(4)=2, cnt(3)=3

提示:

1 <= capacity <= 104
0 <= key <= 105
0 <= value <= 109
最多调用 2 * 105 次 get 和 put 方法
题目链接:leetcode 460 lfu cache
思路,本道题和 LRU cache 类似,在 LRU cache 的基础上需要维护一个统计次数到 cache 中元素的一个字典, cache 中的元素仍然是一个双向链表,除此之外,还需要维护一个变量,统计当前cache 中的元素的最小出现次数(从cache 中删除元素时,需要根据这个值来进行删除)

class ListNode:## 双向链表def __init__(self, key=0, value=0, cnt=1):self.key = key       ### cache 中的 key, key 对应的结果是 ListNode 结构self.value = value        self.prev = Noneself.next = Noneself.cnt = cntclass cntNode:def __init__(self):self.dummy = ListNode()self.dummy.next = self.dummy.prev = self.dummyclass LFUCache:def __init__(self, capacity: int):self.capacity = capacityself.dummy = ListNode()self.dummy.next = self.dummy.prev = self.dummyself.key_to_node = dict()self.minCnt = 1   ## 记录 cache 里面所有 key 的 minCnt## cnt_to_node 存放以计数器为 key 的 valueself.cnt_to_node = collections.defaultdict(cntNode)def append(self, key, value, cnt=1):## 新节点插入到 dummy 节点的 next 节点dummy = self.cnt_to_node[cnt].dummynode1 = ListNode(key, value, cnt)node1.next = dummy.nextdummy.next.prev = node1dummy.next = node1node1.prev = dummyself.key_to_node[key] = node1def delete(self, key):node1 = self.key_to_node[key]node1.prev.next = node1.nextnode1.next.prev = node1.prevnode1.prev = node1.next = Nonedummy = self.cnt_to_node[node1.cnt].dummyif dummy.next == dummy:  ## 如果该 dict 为空,删除该 dictif self.minCnt == node1.cnt:  ## 如果删的是最小的self.minCnt += 1del self.cnt_to_node[node1.cnt]del self.key_to_node[key]def get(self, key: int) -> int:if key in self.key_to_node:node1 = self.key_to_node[key]self.delete(key)newCnt = node1.cnt + 1self.append(key, node1.value, newCnt)return node1.valueelse:return -1def put(self, key: int, value: int) -> None:if key in self.key_to_node:node1 = self.key_to_node[key]self.delete(key)self.append(key, value, node1.cnt+1)else:if len(self.key_to_node) == self.capacity:dummy = self.cnt_to_node[self.minCnt].dummyself.delete(dummy.prev.key)self.append(key, value, 1)self.minCnt = 1# Your LFUCache object will be instantiated and called as such:
# obj = LFUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

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

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

相关文章

高效访问数据的关键:解析MySQL主键自增长的运作机制!

文章目录 &#x1f34a; 主键自增长的概念&#x1f34a; 主键自增长的数据类型&#x1f34a; 主键自增长的步长&#x1f34a; 主键自增长的性能优化&#x1f389; 为什么需要主键自增长的性能优化?&#x1f389; 主键自增长的性能优化方案&#x1f4dd; 1. 调整主键自增长的步…

istio介绍(一)

1. 概念 1.1 虚拟服务 虚拟服务提供流量路由功能&#xff0c;它基于 Istio 和平台提供的基本的连通性和服务发现能力&#xff0c;让您配置如何在服务网格内将请求路由到服务 示例&#xff1a; apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:nam…

【Python机器学习】零基础掌握DictionaryLearning矩阵分解

如何更有效地分析大规模数据? 在现代社会,数据无处不在,尤其是在医疗、金融和营销等领域。然而数据通常是高维度和复杂的,这使得从中提取有用信息变得相当困难。 考虑一个在线营销公司,它每天都会收集大量用户行为数据。这些数据包括用户的浏览历史、点击率和购买记录等…

信钰证券:长江电力180亿市值,招商证券、摩根大通等浮盈超一成

本周A股限售股解禁规划环比有所上升。 Wind数据核算闪现&#xff0c;除去新上市公司&#xff0c;本周共有64家公司限售股解禁&#xff0c;解禁数量51.52亿股&#xff0c;以最新收盘价核算&#xff08;下同&#xff09;&#xff0c;解禁市值776.21亿元。 本周解禁市值跨越10亿…

RN:报错info Opening flipper://null/React?device=React%20Native

背景 在 ios 上使用 debug 模式的时候&#xff0c;报错&#xff1a;info Opening flipper://null/React?deviceReact%20Native&#xff0c;我找到了这个 issue 其实也可以看到现在打开 debug&#xff0c;是 open debug&#xff0c;也不是之前的 debug for chrome 了&#xf…

海外ASO优化之如何优化应用页面上的视频

据统计&#xff0c;观看视频的用户&#xff0c;安装应用的可能性增加了3倍。视频因其动态性而更能吸引注意力&#xff0c;并传达更多有关游戏的信息&#xff0c;强调要点和独特功能&#xff0c;这反过来又会影响转化。 1、技巧。 最重要的部分是视频的前几秒钟。因为这决定了用…

每日一题 2316. 统计无向图中无法互相到达点对数(中等,图连通分量)

题目很简单&#xff0c;只要求出每个连通分量有多少个节点即可首先通过建立一个字典来表示每个节点的邻接关系遍历每个节点&#xff0c;并通过邻接关系标记在当前连通分量内的所有的点&#xff0c;这样就可以知道一个连通分量内有多少个点在这里我陷入了一个误区&#xff0c;导…

计算机系统概论

1. 现代计算机由哪两部分组成 计算机系统&#xff1a;硬件、软件

CSP-S 2023 总结

CSP-S 2023 总结 第一次搞csp-s复赛&#xff0c;感觉没考好。 估分 185&#xff0c;感觉要寄。 先全部看一遍&#xff0c;第三题看了一眼就走了&#xff0c;其他题大概有一点思路&#xff0c;感觉大概150的样子。 T1一开始读错题乱搞了30分钟才发现&#xff0c;然后又花了1…

分享一下抽奖活动小程序怎么做

在当今数字化时代&#xff0c;抽奖活动小程序已成为一种高效、创新的营销方式。它不仅能够吸引用户的注意力&#xff0c;提高品牌知名度&#xff0c;还能促进用户参与度&#xff0c;增强用户对品牌的忠诚度。本文将详细介绍如何制作一个成功的抽奖活动小程序&#xff0c;以及它…

Python爬虫如何设置代理服务器(搭建代理服务器教程)

在Python爬虫中使用代理服务器可以提高爬取数据的效率和稳定性。本文将为您提供搭建代理服务器的详细教程&#xff0c;并提供示例代码&#xff0c;帮助您在Python爬虫中设置代理服务器&#xff0c;实现更高效、稳定的数据抓取。 Python爬虫怎么设置代理服务器&#xff08;搭建代…

Docker修改数据存储目录

1、修改docker默认数据存储目录配置&#xff0c;在/etc/docker/daemon.json文件添加 以下内容 ## 新建docker配置文件touch /etc/docker/daemon.json## 编辑 配置文件添加 "data-root": "/data/docker"vim /etc/docker/daemon.json## 内容如下&#xff1a;…

python打包和发布package

打包 偶尔有一些复用性很高&#xff0c;复杂度也很高的函数要反复调用&#xff0c;可以自行打包&#xff0c;安装 打包结构如下 以iso_timer为例 mkdir common vim __init__.py cd common vim __init__.py vim format.py# init.py from .common import *# /common/init.p…

C++11 正则表达式详解

目录 1 正则表达式语法1.1 字符和特殊字符1.2 限定符1.3 定位符1.4 选择和反向引用 2 C正则表达式标准库常用接口3 C正则表达式模板的使用3.1 匹配&#xff08;Match&#xff09;3.2 搜索&#xff08;Search&#xff09;3.3 分词&#xff08;Tokenize&#xff09;3.4 替换&…

Python —— hou.NetworkItem class

在一个network内&#xff0c;所有可见元素的基类&#xff1b; 此类没有方法&#xff0c;仅作为 hou.NetworkMovabelItem、hou.NodeConnection 基类存在&#xff0c;这两个子类在网络编辑器内均是可见的&#xff0c;是没有真正有意义的基类的&#xff1b;通过提供一个公共的基类…

【干货】Java函数式编程公式大全,收藏学习!

函数操作是现代编程领域中的核心概念之一&#xff0c;它以类似 Excel 表格的方式进行数据处理和计算。它的特点是使用公式和函数来描述数据之间的关系和计算逻辑&#xff1b;它允许我们以更高效、更有组织的方式管理和处理数据。 在函数式编程中&#xff0c;数据被组织成表格的…

Arm推出Total Design生态系统,优化基于Neoverse CSS的SoC开发流程

目录 构建生态系统 将Arm架构小芯片带给大众 关于Arm Total Design的结语 我们最近报道了Arm的Neoverse CSS Genesis N2平台的发布&#xff0c;这是一个近乎现成的计算子系统设计&#xff0c;旨在加快尖端基础设施中定制加速器的上市时间。我们当时评论说&#xff0c;我们可…

flink的TwoPhaseCommitSinkFunction怎么做才能提供精准一次保证

背景 TwoPhaseCommitSinkFunction是flink中基于二阶段事务提交和检查点机制配合使用实现的精准一次的输出数据汇&#xff0c;但是想要实现精准一次的输出&#xff0c;实际使用中需要注意几个方面&#xff0c;否则不仅仅达不到精准一次输出&#xff0c;反而可能导致数据丢失&am…

LongAdder为什么在高并发下保持良好性能?LongAdder源码详细分析

文章目录 一、LongAdder概述1、为什么用LongAdder2、LongAdder使用3、LongAdder继承关系图4、总述&#xff1a;LongAdder为什么这么快5、基本原理 二、Striped64源码分析1、Striped64重要概念2、Striped64常用变量或方法3、静态代码块初始化UNSAFE4、casBase方法5、casCellsBus…

如何利用验证链技术减少大型语言模型中的幻觉

一、前言 随着大型语言模型在自然语言处理领域取得了惊人的进步。相信深度使用过大模型产品的朋友都会发现一个问题&#xff0c;就是有时候在上下文内容比较多&#xff0c;对话比较长&#xff0c;或者是模型本身知识不了解的情况下与GPT模型对话&#xff0c;模型反馈出来的结果…