【Hot100】LeetCode—146. LRU 缓存

news2024/11/25 4:34:06

目录

  • 1-思路
    • 1-1 LRU知识点
    • 1-2 实现思路
      • LRU的子数据结构
        • ① 双向链表 DLinkedNode 结点定义
        • ② 其他字段
      • LRU实现的方法
        • ① 初始化——LRUCache中初始化
        • ② public int get(int key) 取元素方法
        • ③ public void put(int key, int value) 存元素方法
  • 2-实现
    • ⭐146. LRU 缓存——题解思路
  • 3- ACM实现


  • 原题连接:146. LRU 缓存

1-思路

1-1 LRU知识点

  • LRU :最近最少使用算法,如果经常请求的数据不会被淘汰,会被淘汰的是最近最少请求的数据。
  • 热门数据会往上排列

image.png

  • 看到 LRU,就想到 LRU 对应的数据结构 ——> HashMap + 双向链表(DLinkedNode)

image.png


1-2 实现思路

LRU 算法的具体步骤

  • 1- 头插: 新数据直接插入到列表头部
  • 2- 移动到头: 缓存数据被命中,将数据移动到列表头部
  • 3- 删除尾部: 缓存已经满的时候,移除列表尾部数据

LRU的子数据结构

① 双向链表 DLinkedNode 结点定义
  • 包含 keyvaluekey 就是 HashMapkey
class DLinkedNode{
    int key;
    int value;
    DLinkedNode pre;
    DLinkedNode next;
    DLinkedNode(){}
    DLinkedNode(int k,int v){key = k; value = v;}
}
② 其他字段
  • cache :缓存 Map<Integer,DLinkedNode> :key 放 key,value 放值
  • size:当前缓存中的元素个数
  • capacity:缓存的容量
  • DLinkedNode head,tail:定义双向链表的头尾结点
Map<Integer,DLinkedNode> cache = new HashMap<Integer,DLinkedNode>();
int size;
int capacity;
DLinkedNode head,tail;

LRU实现的方法

① 初始化——LRUCache中初始化
  • 根据 capacity 传入的容量进行初始化
    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.pre = head;
    }
② public int get(int key) 取元素方法

image.png
获取元素涉及到的方法如下

  • 1- public int get(int key)
    • 通过 key 获取元素,直接使用 mapget方法
    • 若不存在,返回 -1
    • 若存在,先将其 moveToHead(DLinkedNode node) 再返回
  • 2- moveToHead(DLinkedNode node)
    • private DLinkedNode remove(DLinkedNode node):先删除node元素
    • private void addToHead(DLinkedNode node)再添加到头
  • 3- remove(DLinkedNode node)
    • 双链表 删除 node 结点
  • 4- addToHead(DLinkedNode node)
    • 双链表头插

image.png


③ public void put(int key, int value) 存元素方法
  • 添加元素思考:
    • 当前元素不存在,直接添加,添加过程中需要判断缓存是否已满
    • 若存在,更新 value 即可

image.png


2-实现

⭐146. LRU 缓存——题解思路

在这里插入图片描述
在这里插入图片描述

class LRUCache {

    public class DLinkedNode{
        int key;
        int val;
        DLinkedNode pre;
        DLinkedNode next;
        DLinkedNode(){}
        DLinkedNode(int k,int v){
            key = k;
            val = v;
        }
    }
    // 定义 LRU 所需要的变量
    HashMap<Integer,DLinkedNode> cache = new HashMap<>();
    int capacity;
    int size;
    DLinkedNode head,tail;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.size = 0;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.pre = head;
    }
    
    public int get(int key) {
        // get 元素
        DLinkedNode node = cache.get(key);
        if(node==null){
            return -1;
        }
        // 双链表操作
        moveToHead(node);
        return node.val;
    }

    private void moveToHead(DLinkedNode node){
        remove(node);
        addToHead(node);
    }

    private void remove(DLinkedNode node){
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }
    
    private void addToHead(DLinkedNode node){
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
        node.pre = head;
    }

    public void put(int key, int value) {
        // 要判断是更新还是新增
        DLinkedNode node = cache.get(key);
        if(node==null){
            DLinkedNode newNode = new DLinkedNode(key,value);
            cache.put(key,newNode);
            size++;
            addToHead(newNode);
            if(size>capacity){
                DLinkedNode last = removeLast();
                cache.remove(last.key);
                size--;
            }
        }else{
            node.val = value;
            moveToHead(node);
        }
    }

    public DLinkedNode removeLast(){
        DLinkedNode last = tail.pre;
        remove(last);
        return last;
    }
}

3- ACM实现


import java.util.HashMap;
import java.util.Scanner;


public class LRUCache {


    // 1- 定义数据
    class DLinkedNode{
        int key;
        int value;
        DLinkedNode pre;
        DLinkedNode next;
        DLinkedNode(){}
        DLinkedNode(int k,int v){
            key = k;
            value = v;
        }
    }
    int size;
    int capacity;
    DLinkedNode head,tail;
    HashMap<Integer,DLinkedNode> cache = new HashMap<>();

    // 2- 初始化
    public LRUCache(int capacity){
        this.capacity = capacity;
        this.size = 0;
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.pre = head;
    }


    // 3- 实现 LRU 的get方法
    public int get(int key){
        DLinkedNode node = cache.get(key);
        if(node== null){
            return -1;
        }
        moveToHead(node);
        return node.value;
    }

    private void moveToHead(DLinkedNode node){
        remove(node);
        addToHead(node);
    }

    private void remove(DLinkedNode node){
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    private void addToHead(DLinkedNode node){
        node.next = head.next;
        head.next.pre = node;
        head.next = node;
        node.pre = head;
    }

    // 4- 实现 LRU 的put方法
    public void put(int key,int value){
        DLinkedNode node = cache.get(key);
        if(node==null){
            node = new DLinkedNode(key,value);
            cache.put(key,node);
            addToHead(node);
            size++;
            if(size>capacity){
                DLinkedNode ttail = removeTail();
                cache.remove(ttail.key);
                size--;
            }
        }
    }

    private DLinkedNode removeTail(){
        DLinkedNode node = tail.pre;
        remove(node);
        return node;
    }


    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入cache缓存容量capacity");
        int capacity = scanner.nextInt();
        LRUCache cache = new LRUCache(capacity);
        while (scanner.hasNext()) {
            String operation = scanner.next();
            if (operation.equals("get")) {
                int key = scanner.nextInt();
                System.out.println(cache.get(key));
            } else if (operation.equals("put")) {
                int key = scanner.nextInt();
                int value = scanner.nextInt();
                cache.put(key, value);
            }
        }
        scanner.close();
    }
}


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

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

相关文章

rufus制作ubantu的U盘安装介质时,rufus界面上的分区类型选什么?

rufus制作ubantu的U盘安装介质时&#xff0c;rufus软件界面上的分区类型选什么(如下图&#xff09;&#xff1f; 在使用Rufus制作Ubuntu的U盘安装介质时&#xff0c;分区类型的选择取决于我们的计算机的引导方式。 以下是具体的选择建议&#xff1a; 1、查看计算机的引导方式…

JAVA设计模式之【单例模式】

1 类图 2 饿汉式单例 例如&#xff1a;静态块、静态成员 2.1 概念 类加载的时候就立即初始化&#xff0c;并且创建单例对象 2.2 优点 没有加任何的锁、执行效率比较高 2.3 缺点 类加载的时候就初始化&#xff0c;不管用与不用都占着空间&#xff0c;浪费了内存。 3 懒汉…

Java之迭代器的使用

Java之迭代器的使用 摘要基础知识List迭代器Map迭代器 摘要 本博客主要讲解容器的迭代器的使用&#xff0c;包括List、Set和Map等容器 基础知识 这是类的继承关系图 迭代器的原理(一开始迭代器并不指向任何有效元素)&#xff1a; List迭代器 public class TestIterator …

VMware vSphere Client无法访问和连接ESXi虚拟主机解决思路

文章目录 前言1. 问题现象2. 问题原因3. 解决方法4. 参考文章 前言 注意 : 可以先看看参考文章那里&#xff0c;在回过来看 1 、 2 、3 1. 问题现象 版本&#xff1a;VMware vCenter Server 5.5.0 build-2442329 问题描述&#xff1a;用VMware vSphere Client 登录ESXI主机出…

【Linux —— 线程互斥】

Linux —— 线程互斥 1. 临界资源与临界区2. 互斥的定义3. 原子性4. 互斥量(Mutex)5. 互斥的实现示例 1. 临界资源与临界区 临界资源: 指的是多个线程或进程共享的资源&#xff0c;例如全局变量、文件、数据库等。由于这些资源的共享&#xff0c;可能会导致数据不一致或程序崩…

git commit 时发生:fatal: cannot lock HEAD ref

.git目录探析_.git文件在哪-CSDN博客https://blog.csdn.net/luofeng457/article/details/117577275 tree .git .git ├── branches ├── COMMIT_EDITMSG ├── config ├── description ├── FETCH_HEAD ├── HEAD ├── hooks │ ├── applypatch-msg.sample…

STM32的GPIO

GPIO基本控制 GPIO(General-Purpose input/output,通用输入/输出接口) 用于感知外部信号&#xff08;输入模式&#xff09;和控制外部设备&#xff08;输出模式&#xff09; 简单模块&#xff1a;LED,按键&#xff0c;蜂鸣器&#xff0c;温度传感器&#xff0c;使用一个GPIO…

qt-PLC可视化编辑器

qt-PLC可视化编辑器 一、演示效果二、核心代码三、下载链接 一、演示效果 二、核心代码 #include "diagramitem.h" #include "arrow.h"#include <QDebug> #include <QGraphicsScene> #include <QGraphicsSceneContextMenuEvent> #includ…

1 Kubeflow总体介绍-学习笔记

1 什么是 Kubeflow Kubeflow 是一个开源项目社区和生态系统&#xff0c;支持机器学习 (ML) 生命周期中的每个阶段 &#xff0c;并支持相关的开源 工具和框架&#xff0c;Kubeflow 使 Kubernetes 上的 AI/ML 变得简单、可移植且可扩展。 Kubeflow 都能提供模块化、可扩展的工具…

C语言第17篇

1.在C语言中,全局变量的存储类别是_________. A) static B) extern C) void D) register 提示&#xff1a;extern adj.外来的 register n.登记表&#xff0c;v.登记 提示与本题无关 2.在一个C源程序文件中,要定义一个只允许本源文件中所有函数使用的全局变…

JimuReport 积木报表 v1.8.0 版本发布,开源可视化报表

项目介绍 一款免费的数据可视化报表工具&#xff0c;含报表和大屏设计&#xff0c;像搭建积木一样在线设计报表&#xff01;功能涵盖&#xff0c;数据报表、打印设计、图表报表、大屏设计等&#xff01; Web 版报表设计器&#xff0c;类似于excel操作风格&#xff0c;通过拖拽完…

【Python】成功解决 NameError: name ‘reload‘ is not defined

【Python】成功解决 NameError: name ‘reload’ is not defined 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校…

【学习笔记】7、存储器、复杂可编程器件和现场可编程门阵列

可编程逻辑器件PLD复杂可编程逻辑器件CPLD现场可编程门阵列FPGA 7.1 只读存储器&#xff08;ROM&#xff09; 7.1.1 ROM的结构 ROM存储器 存储阵列 地址译码器 输出控制电路 存储阵列&#xff0c;由许多存储单元&#xff08;1bit&#xff09;组成。每次读出一组数据&…

HTML实现俄罗斯方块

本篇文章主要讲使用HTML、CSS和JavaScript实现一个简单的俄罗斯方块游戏&#xff0c;包含基本的游戏逻辑、行消除功能以及暂停和继续游戏的控制。 使用工具 本篇文章有用到ChatGPT-4o代码纠错&#xff0c;国内免翻且稳定&#xff0c;感兴趣的大佬试试。 传送门&#xff1a;36…

认知杂谈20

今天分享 有人说的一段争议性的话 I I 程序员的高薪舒适圈&#xff1a;光鲜背后的挑战 一说起程序员这个职业&#xff0c;很多人马上就会想到高薪&#xff0c;觉得他们过着白领的生活。确实&#xff0c;程序员一般都能拿到比好多行业都高的工资&#xff0c;工作时间也比较稳…

谷粒商城实战笔记-232-商城业务-认证服务-框架效果演示-xxl-sso-徐雪里

文章目录 一&#xff0c;膜拜大神许雪里二&#xff0c;用开源框架xxl-sso演示单点登录1&#xff0c;我是老板&#xff0c;我有三个网站2&#xff0c;配置域名3&#xff0c;下载xxl-sso代码4&#xff0c;服务规划5&#xff0c;配置修改5.1 xxl-sso-server redis配置修改5.1 xxl-…

使用FModel提取黑神话悟空的资产

使用FModel提取黑神话悟空的资产 前言设置效果展示闲聊可能遇到的问题没有相应的UE引擎版本选项 前言 黑神话悟空昨天上线了&#xff0c;解个包looklook。 本文内容比较简洁&#xff0c;仅介绍解包黑神话所需的专项配置&#xff0c;关于FModel的基础使用流程&#xff0c;请见…

Python3学习(一)

目录 Python版本 标识符 保留字 注释 缩进 多行语句 同一行显示多条语句 import 与 from...import 变量 数据类型 Number&#xff08;数字&#xff09; 数字类型 数值运算 String&#xff08;字符串&#xff09; bool&#xff08;布尔类型) List&#xff08;列…

废品回收小程序,开启上门回收模式

废品回收一直是一个热门行业&#xff0c;市场发展空间巨大。随着科技的发展&#xff0c;废品回收也与时俱进&#xff0c;进行了转型&#xff01;“互联网上门回收”的新模式&#xff0c;运用信息技术的力量&#xff0c;让废品回收变得更加高效便捷&#xff0c;同时也为回收行业…

秋招红队面试经验分享

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》 《Java代码审计》 《Web安全…