leetcode-146. LRU 缓存

ops/2024/10/30 3:10:49/

题目描述

请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

思路

使用双向链表来完成,参考:. - 力扣(LeetCode)

1)需要创建一个链表结构【key,value,prev,next】

2)初始化:容器的容量,hash字典,双向链表的构建

3)定义一个将节点移动到末尾的函数【最新被访问的节点都放在队尾】

    3.1)从hash字典里读取这个节点

    3.2)缝合这个节点的前后

    3.3)这个节点插入到尾部节点之前

4)get操作:如果key值在hash字典里,就先移动到队尾;从hash字典里获取key的值,如果不等于-1就返回其value

5)put操作:如果key在hash字典里,就更新该key在hash字典里的value,并将其移动到队尾;如果没在过,就先看是否当前的hash字典已经满足容量里,如果满足:则移除头节点后面的节点,之后进行缝合;

    5.1)新建一个节点,放入hash字典中;将新节点插入到尾部节点之前

ps:一般插入操作都是4步,node.next,node.prev;之后插入的位置前节点指向该节点,后面的节点指向该节点

class ListNode:def __init__(self, key=None, value=None):self.key = keyself.value = valueself.prev = Noneself.next = Noneclass LRUCache(object):def __init__(self, capacity):""":type capacity: int"""self.capacity = capacityself.hashmap = {}self.head = ListNode()self.tail = ListNode()self.head.next = self.tailself.tail.prev = self.headdef move_node_to_tail(self, key):node = self.hashmap[key]node.prev.next = node.nextnode.next.prev = node.prevnode.next = self.tailnode.prev = self.tail.prevself.tail.prev.next = nodeself.tail.prev = node def get(self, key):""":type key: int:rtype: int"""if key in self.hashmap:self.move_node_to_tail(key)res = self.hashmap.get(key,-1)if res == -1:return res else:return res.valuedef put(self, key, value):""":type key: int:type value: int:rtype: None"""if key in self.hashmap:self.hashmap[key].value = valueself.move_node_to_tail(key)else:if len(self.hashmap) == self.capacity:self.hashmap.pop(self.head.next.key)self.head.next = self.head.next.nextself.head.next.prev = self.headnew = ListNode(key, value)self.hashmap[key] = new new.next = self.tailnew.prev = self.tail.prevself.tail.prev.next = newself.tail.prev = new# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

http://www.ppmy.cn/ops/129472.html

相关文章

oracle数据库---PL/SQL、存储函数、存储过程、触发器、定时器job、备份

PL/SQL 什么是 PL/SQL PL/SQL(Procedure Language/SQL)是 Oracle 对 sql 语言的过程化扩展,指在 SQL 命令语言中增加了过程处理语句(如分支、循环等),使 SQL 语言具有过程处理能力。把SQL语言的数据操纵能…

三防加固工业平板国产化的现状与展望

在当今全球科技竞争日益激烈的背景下,工业4.0和智能制造的浪潮推动了工业自动化设备的迅速发展,其中,三防加固工业平板电脑作为连接物理世界与数字世界的桥梁,其重要性不言而喻。所谓“三防”,即防水、防尘、防震&…

LabVIEW提高开发效率技巧----插入式架构

随着LabVIEW项目规模的扩大和系统复杂性的增加,传统的单一代码架构难以应对后期维护和功能扩展的需求。插入式架构(Plug-In Architecture)作为一种模块化设计方式,通过动态加载和运行子VI,使系统功能更加灵活、模块化&…

交叉编译 perl-5.40.0(riscv64)

交叉编译 perl-5.40.0(riscv64) https://arsv.github.io/perl-cross/usage.html https://github.com/arsv/perl-cross 借助 perl-cross 进行交叉编译 https://www.perl.org/get.html#unix_like 这里获取 perl-5.40.0 的源码 https://github.com/arsv/pe…

安装双系统后ubuntu无法联网(没有wifi标识)网卡驱动为RTL8852BE

安装双系统后ubuntu没有办法联网,(本篇博客适用的版本为ubuntu20.04)且针对情况为无线网卡驱动未安装的情况 此时没有网络,可以使用手机数据线连接,使用USB共享网络便可解决无法下载的问题。 打开终端使用命令lshw -C …

三款计算服务器配置→如何选择科学计算服务器?

科学计算在众多领域都扮演着关键角色,无论是基础科学研究还是实际工程应用,强大的计算能力都是不可或缺的。而选择一台合适的科学计算服务器,对于确保科研和工作的顺利进行至关重要。 首先,明确自身需求是重中之重。要仔细考虑计算…

基于Java(SSM框架)+MySQL 开发的停车场管理系统

基于SSM的停车场管理系统的设计与实现 摘要 自从进入21 世纪以后,汽车产业迅速发展,伴随着人们生活程度的日益进步的人口的迅速增加,汽车的数量也如雨后春笋般在城市里不断的增加。这种现象,一方面是值得我们高兴的,…

自动驾驶-传感器简述

自动驾驶车辆上的传感器类型包含激光雷达、毫米波雷达、相机、imu、rtk、超声波雷达等,这些传感器用来接收外部世界多姿多彩的信号,根据接收到的信号,车载大脑对信号进行处理,那信号的准确程度就尤为重要。 本文将各个传感器的特性…