leetcode刷题记录(七十二)——146. LRU 缓存

(一)问题描述

146. LRU 缓存 - 力扣(LeetCode)146. LRU 缓存 - 请你设计并实现一个满足  LRU (最近最少使用) 缓存 [https://baike.baidu.com/item/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); // 返回 1lRUCache.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); // 返回 3lRUCache.get(4); // 返回 4 提示: * 1 <= capacity <= 3000 * 0 <= key <= 10000 * 0 <= value <= 105 * 最多调用 2 * 105 次 get 和 puthttps://leetcode.cn/problems/lru-cache/description/?envType=study-plan-v2&envId=top-100-liked

请你设计并实现一个满足  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

 

提示:

  • 1 <= capacity <= 3000
  • 0 <= key <= 10000
  • 0 <= value <= 105
  • 最多调用 2 * 105 次 get 和 put

(二)解决思路

        这道题以方便要用哈希表方便查找,另一方面可以用双向链表来记录节点被使用的顺序:新增的元素和刚刚被修改了value的元素放在头部,如果插入时节点数量超过了capacity,就把尾部元素删掉。使用双向链表和使用单向链表相比便于操作尾部元素。

 方法一:使用现成的数据结构

        python和java中都有存在哈希功能的链表结构,python是OrderedDict,java是LinkedHashMap。但是直接用已有的数据结构一般不会符合面试官的要求,和库函数的使用一样,有些数据结构的使用也要慎重,像这种直接用数据结构的情况明显是跳过了问题想要考察的重点

        下面的代码来自Leetcode官方题解。 

class LRUCache extends LinkedHashMap<Integer, Integer>{private int capacity;public LRUCache(int capacity) {super(capacity, 0.75F, true);this.capacity = capacity;}public int get(int key) {return super.getOrDefault(key, -1);}public void put(int key, int value) {super.put(key, value);}@Overrideprotected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {return size() > capacity; }
}

方法二:哈希表+双向链表 

         面试官会更希望我们自己实现哈希表+双向链表的功能。思路就是本节开头的那段话。链表的定义其实就是节点类的定义。为了方便插入和删除头尾元素,可以创建虚拟头尾节点head和tail。

class LRUCache {//双向链表class DLinkedNode{public int key;public int value;public DLinkedNode prev;public DLinkedNode next;public DLinkedNode(){};public DLinkedNode(int _key,int _value){key=_key;value=_value;}}//哈希表private HashMap<Integer,DLinkedNode> cache=new HashMap<>();//size是现在链表的长度,capacity是允许的最大节点数private int size;private int capacity;//虚拟头尾节点private DLinkedNode head,tail;public LRUCache(int capacity) {//大部分时候访问类自身的成员变量不需要this//但是如果方法里有某个局部变量和成员变量名字相同,就需要用this区分this.size=0;this.capacity=capacity;head=new DLinkedNode();tail=new DLinkedNode();head.next=tail;tail.prev=head;}public int get(int key) {//判断map里是否存在key,如果不存在的话会返回nullDLinkedNode node=cache.get(key);if(node==null){return -1;}else{//刚刚访问过的节点移动到头部moveToHead(node);return node.value;}}public void put(int key, int value) {//判断map里是否存在key,如果不存在的话会返回null//如果只是map存或者更新value的话不需要判断,但这里还涉及链表的变化,所以要判断DLinkedNode node=cache.get(key);if(node==null){//新节点加入DLinkedNode newNode=new DLinkedNode(key,value);//新节点放在链表头putToHead(newNode);//节点放进mapcache.put(key,newNode);size++;if(size>capacity){//超出容量,删除尾部节点int removeKey=removeFromTail();cache.remove(removeKey);}}else{//已经存在的节点更新值node.value=value;//放在节点头moveToHead(node);}}//节点的移动/添加就是指针指向的变化public void moveToHead(DLinkedNode node){node.prev.next=node.next;node.next.prev=node.prev;node.next=head.next;head.next.prev=node;head.next=node;node.prev=head;}public void putToHead(DLinkedNode newNode){head.next.prev=newNode;newNode.next=head.next;head.next=newNode;newNode.prev=head;}public int removeFromTail(){DLinkedNode node=tail.prev;node.next.prev=node.prev;node.prev.next=node.next;return node.key;}
}

 注:大部分时候访问类自身的成员变量不需要this,但是如果方法里有某个局部变量和成员变量名字相同,就需要用this区分。

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

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

相关文章

微信小程序:实现单选,多选,通过变量控制单选/多选

一、实现单选功能 微信小程序提供了 radio 组件来实现单选功能。radio 组件需要配合 radio-group 使用。 1. WXML 代码 <radio-group bindchange"onRadioChange"><label wx:for"{{items}}" wx:key"id"><radio value"{{it…

vue2使用flv.js在浏览器打开flv格式视频

组件地址&#xff1a;GitHub - bilibili/flv.js: HTML5 FLV Player flv.js 仅支持 H.264 和 AAC/MP3 编码的 FLV 文件。如果视频文件使用了其他编码格式就打不开。 flv.vue <template><div><el-dialog :visible.sync"innerVisibleFlv" :close-on-pre…

Spring 中的事件驱动模型

事件驱动的基本了解 事件模式也就是观察者模式&#xff0c;当一个对象改变的时候&#xff0c;所有依赖的对象都会收到一个通知。 Subject&#xff1a;抽象主题 Observer&#xff1a;具体主题 Concrete Subject&#xff1a;抽象观察者&#xff0c;在得到更新通知之后去更新自…

STM32补充——IAP

0 前置知识&#xff1a; FLASH相关内容&#xff1a;前往STM32补充——FLASH STM32三种烧录方式&#xff08;看看就行&#xff09;&#xff1a; 1.ISP&#xff1a;In System Programming&#xff08;在系统编程&#xff09; 执行芯片厂商的 Bootloader 程序进入 ISP 模式&…

k8s的CICD实施项目

环境需求&#xff1a; 目前领导需要做一个需求&#xff0c;临时把我从运维岗位&#xff0c;把我调度到到专家组让我主导cicd的项目实施 目前环境资源 k8s环境&#xff0c;28台服务器&#xff0c;上面是k8s集群&#xff0c;要实施一个测试环境的cicd以及一个生产环境的cicd gitl…

【线性代数】基础版本的高斯消元法

[精确算法] 高斯消元法求线性方程组 线性方程组 考虑线性方程组&#xff0c; 已知 A ∈ R n , n , b ∈ R n A\in \mathbb{R}^{n,n},b\in \mathbb{R}^n A∈Rn,n,b∈Rn&#xff0c; 求未知 x ∈ R n x\in \mathbb{R}^n x∈Rn A 1 , 1 x 1 A 1 , 2 x 2 ⋯ A 1 , n x n b 1…

AIGC视频生成模型:Runway的Gen系列模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Runway开发的视频生成模型Gen系列&#xff0c;包括Gen-1、Gen-2和Gen3 Alpha等&#xff0c;这些模型每次发布都震惊AI圈&#xff0c;荣获多个视频生成的…

【JVM-9】Java性能调优利器:jmap工具使用指南与应用案例

在Java应用程序的性能调优和故障排查中&#xff0c;jmap&#xff08;Java Memory Map&#xff09;是一个不可或缺的工具。它可以帮助开发者分析Java堆内存的使用情况&#xff0c;生成堆转储文件&#xff08;Heap Dump&#xff09;&#xff0c;并查看内存中的对象分布。无论是内…

【基于无线电的数据通信链】Link 11 仿真测试

〇、废话 Link 11 仿真测试 涉及多个方面&#xff0c;包括信号仿真、协议模拟、数据链路层的仿真以及网络性能评估等。Link 11 是一种基于 HF&#xff08;高频&#xff09; 或 UHF&#xff08;超高频&#xff09; 波段的无线通信协议&#xff0c;主要用于军事通信系统中。为了…

AG32 FPGA 的 Block RAM 资源:M9K 使用

1. 概述 AG32 FPGA 包含了 4 个 M9K 块&#xff0c;每个 M9K 块的容量为 8192 bits&#xff0c;总计为 4 个 M9K&#xff08;4K bytes&#xff09;。这使得 AG32 的内部存储非常适合嵌入式应用&#xff0c;能够有效地利用片上资源。 M9K 参数 参考自《AGRV2K_Rev2.0.pdf》。…

【算法笔记】力扣热题100(LeetCode hot-100)438. 找到字符串中所有字母异位词 滑动窗口

力扣热题100&#xff08;LeetCode hot-100&#xff09;之 438. 找到字符串中所有字母异位词 本文主要记录算法思路&#xff0c;着急要答案的同学可以直接跳转到最后的代码。 题目 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子…

【Python】深入探讨Python中的单例模式:元类与装饰器实现方式分析与代码示例

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门&#xff01; 解锁Python编程的无限可能&#xff1a;《奇妙的Python》带你漫游代码世界 单例模式&#xff08;Singleton Pattern&#xff09;是一种常见的设计模式&#xff0c;它确保一个类只有一个实例&…

Hadoop•搭建完全分布式集群

听说这里是目录哦 一、安装Hadoop&#x1f955;二、配置Hadoop系统环境变量&#x1f96e;三、验证Hadoop系统环境变量是否配置成功&#x1f9c1;四、修改Hadoop配置文件&#x1f36d;五、分发Hadoop安装目录&#x1f9cb;六、分发系统环境变量文件&#x1f368;七、格式化HDFS文…

【机器人学】2-3.六自由度机器人运动学逆解-工业机器人【附MATLAB代码】

解析解推导 假设有一工业机器人参数如下图所示&#xff1a; matlab代码 clc;clear; %带入机器人初始值 d1 0.670; d4 1.280; d6 0.215;a2 0.312; a3 1.075; a4 0.225;Position[288.1, -433.1, 2832,96.9158, -29.6162, 109.3547]; px Position(1)/1000; py Positio…

ARM学习(42)CortexM3/M4 MPU配置

笔者之前学习过CortexR5的MPU配置,现在学习一下CortexM3/M4 MPU配置 1、背景介绍 笔者在工作中遇到NXP MPU在访问异常地址时,就会出现总线挂死,所以需要MPU抓住异常,就需要配置MPU。具体背景情况可以参考ARM学习(41)NXP MCU总线挂死,CPU could not be halted以及无法连…

HTML语言的数据结构

HTML语言的数据结构 引言 HTML&#xff08;超文本标记语言&#xff09;是构建网页的标准语言。尽管HTML本身不是一种编程语言&#xff0c;它为我们提供了一种结构化的信息表示方法&#xff0c;使得网页内容能够有序地展现给用户。HTML的核心在于其标记&#xff08;标签&#…

PIC单片机HEX文件格式分析

在调试PIC单片机在bootloader程序时&#xff0c;需要将hex文件转换为bin文件&#xff0c;在转换之前先了解一下hex文件中数据是如何定义的。 直接打开一个LED灯闪烁的程序生成的hex文件&#xff0c;芯片型号为PIC18F46K80 可以看到每条数据都是由6部分组成的&#xff0c;下面分…

利用Kubespray安装生产环境的k8s集群-实施篇

如何安装生产环境下的高可用k8s集群 接上篇 规划k8s集群 本次我预备了6台VMs&#xff0c; 1台作为Jump server&#xff0c;用来部署Ansible并负责在其他5台设备上部署k8s。这台服务器后续可能还要做nfs server。 3台做master&#xff0c;为了给etcd做高可用。&#xff08;Et…

SQL中字符串截取函数(substring)

1.left&#xff08;name&#xff0c;4&#xff09;截取左边的四个字符 案例 select left(20240428,4) 结果 2024 2.right&#xff08;name&#xff0c;2&#xff09;截取右边的2个字符 案例 select right(20240428,2) 结果 28 3.substring(name,5,3)截取name这个字段从第五个字…

用户中心项目教程(四)---Vue脚手架完成前端初始化

目录 1.项目的创建 2.使用开发工具打开 3.项目运行方法 4.使用按钮组件 5.全局注册 6.如何进行组件的测试 7.使用组件的效果展示 8.关于这个vue项目内容的说明 1.项目的创建 这个前提你是你完成了我的教程&#xff08;三&#xff09;里面的相关配置&#xff0c;不然你可…