Java算法_ LRU 缓存(LeetCode_Hot100)

news2024/11/24 15:38:49

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

获得更多?算法思路:代码文档,算法解析的私得。

运行效果
在这里插入图片描述

完整代码

import java.util.HashMap;
import java.util.Map;

/**
 * 2 * @Author: LJJ
 * 3 * @Date: 2023/8/7 13:14
 * 4
 */
public class LRUCache {
    class Node{
        int key;
        String value;
        Node prev;
        Node next;

        public Node(int key , String value){
            this.key = key;
            this.value = value;
        }
    }

    private int capacity;
    private Map<Integer,Node> cache;
    private Node head;
    private Node tail;

    // 初始化LRUCache类的构造函数,
    // 使用了一个哨兵节点的技巧,将head和tail初始化为哨兵节点,并不存储具体的键值对。
    // 哨兵节点可以简化链表的操作,避免处理头部和尾部节点时需要特殊处理的情况。
    public LRUCache(int capacity){
        this.capacity = capacity;
        cache = new HashMap<>();
        //初始化头尾节点;
        head = new Node(-1, "-1");
        tail = new Node(-1, "-1");
        head.next = tail;
        tail.prev = head;
    }

    public String get(int key){
       if (cache.containsKey(key)){
            Node node = cache.get(key);
            //将查到的节点移动到链表头部
            removeNode(node);
            addToHead(node);
            return node.value;
        }
        return "-1";
    }

    public void put(int key, String value){
        if (cache.containsKey(key)){
            Node node = cache.get(key);
            node.value = value;
            //将更新后的节点移动到链表头部
            removeNode(node);
            addToHead(node);
        }else {
            if (cache.size() >= capacity){

                //如果缓存已满,需要移除最久未使用的节点(即链表尾部节点)
                cache.remove(tail.prev.key);
                removeNode(tail.prev);
            }
            Node newNode = new Node(key,value);
            cache.put(key,newNode);
            //将新的节点插入链表头部
            addToHead(newNode);
        }
    }

    // 将节点插入链表头部
    private void addToHead(Node node){
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
        node.prev = head;
    }

    //移除节点
    private void removeNode(Node node){
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private static void printCache(Node head){
        Node current = head;
        while (current != null){
            System.out.print("(" + current.key + ", " + current.value + ") -> ");
            current = current.next;
        }
        System.out.println("null");
    }
    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(3);

        // 插入键值对 (1, "A")
        lruCache.put(1, "A");
        // 插入键值对 (2, "B")
        lruCache.put(2, "B");
        // 插入键值对 (3, "C")
        lruCache.put(3, "C");

        // 此时缓存状态为:3 -> 2 -> 1,其中1是最近访问的,3是最久未使用的
        System.out.println("初始缓存状态为:");
        printCache(lruCache.head);
        // 获取键1对应的值,输出"A"
        System.out.println(" // 获取键1对应的值:"+lruCache.get(1));

        // 此时缓存状态不变:1 -> 3 -> 2
        System.out.println("获取键1对应的值,输出\"A\"后的缓存状态为:");
        printCache(lruCache.head);
        // 插入键值对 (4, "D"),此时缓存已满,需要逐出最久未使用的键值对,即键2 -> 值B被逐出
        lruCache.put(4, "D");

        // 此时缓存状态为:4 -> 1 -> 3,其中3是最久未使用的,4是最近访问的
        System.out.println("插入键值对 (4, \"D\"),此时缓存已满,需要逐出最久未使用的键值对,即键2 -> 值B被逐出的缓存状态为:");
        printCache(lruCache.head);
        // 获取键2对应的值,由于键2已经被逐出,输出-1
        System.out.println("获取键2对应的值:"+lruCache.get(2));

        // 此时缓存状态不变:4 -> 1 -> 3
        System.out.println("获取键2对应的值,由于键2已经被逐出,输出-1的缓存状态为:");
        printCache(lruCache.head);
        // 插入键值对 (5, "E"),此时缓存已满,需要逐出最久未使用的键值对,即键3 -> 值C被逐出
        lruCache.put(5, "E");

        // 此时缓存状态为:5 -> 4 -> 1,其中1是最久未使用的,5是最近访问的
        System.out.println("插入键值对 (5, \"E\"),此时缓存已满,需要逐出最久未使用的键值对,即键3 -> 值C被逐出的缓存状态为:");
        printCache(lruCache.head);
        // 获取键3对应的值,由于键3已经被逐出,输出-1
        System.out.println("获取键3对应的值:"+lruCache.get(3));

        // 此时缓存状态不变:5 -> 4 -> 1
        System.out.println(" // 获取键3对应的值,由于键3已经被逐出,输出-1的缓存状态为:");
        printCache(lruCache.head);
    }
}

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

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

相关文章

winform中嵌入cefsharp, 并使用selenium控制

正常说&#xff0c; 需要安装的包 下面是所有的包 全部代码 using OpenQA.Selenium.Chrome; using OpenQA.Selenium; using System; using System.Windows.Forms; using CefSharp.WinForms; using CefSharp;namespace WindowsFormsApp2 {public partial class Form1 : Form{//…

(kubernetes)k8s常用资源管理

目录 k8s常用资源管理 1、创建一个pod 1&#xff09;创建yuml文件 2&#xff09;创建容器 3&#xff09;查看所有pod创建运行状态 4&#xff09;查看指定pod资源 5&#xff09;查看pod运行的详细信息 6&#xff09;验证运行的pod 2、pod管理 1&#xff09;删除pod 2…

搜索二叉树(二叉树进阶)

目录 1.二叉搜索树 1.1二叉搜索树概念 1.2二叉搜索树操作 2.3二叉搜索树的实现 2.4二叉搜索树的应用 2.5二叉搜索树的性能分析 1.二叉搜索树 1.1二叉搜索树概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一颗空树&#xff0c;或者是具有以下性质的二叉树&#xff…

mac安装nvm管理工具遇到的问题和解决方法

nvm 是一款可以管理多版本node的工具&#xff0c;因为是刚买没多久的电脑之前用的都是windows&#xff0c;昨天折腾了一下午终于倒腾好了 第一步&#xff1a; 卸载电脑已有的node&#xff1b;访问nvm脚本网址&#xff0c;另存为到电脑上任何目录&#xff0c;我是放在桌面上的…

OSPF技术入门(第三十四课)

1 OSPF的介绍 OSPF是一种链路状态路由协议,主要用于IP网络中的路由选择。它是一种开放协议,能够在不同的网络设备之间进行通信。OSPF利用链路状态数据库来描述网络拓扑结构,并通过Dijkstra算法计算出最短路径。它支持按照精确度划分的路由优先级,以及多个相等的路径,并能自…

微服务分布式搜索引擎 ElasticSearch 查询文档

文章目录 ⛄引言一、DSL查询文档⛅DSL 查询分类 二、DSL查询实例⛅全文检索查询⏰精确查询⚡地理坐标查询⌚复合查询 ⛵小结 ⛄引言 本文参考黑马 分布式Elastic search Elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海…

服务器数据恢复-断电导致ext4文件系统文件丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 一台服务器挂载一台存储设备&#xff0c;存储中划分一个Lun&#xff1b;服务器操作系统是Linux centos&#xff0c;EXT4文件系统。 服务器故障&分析&#xff1a; 意外断电导致服务器操作系统无法启动&#xff0c;系统在修复后可以正常启动&…

竞赛项目 深度学习的动物识别

文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…

在Ubuntu中使用Docker启动MySQL8的天坑

写在前面 简介&#xff1a; lower_case_table_names 是mysql设置大小写是否敏感的一个参数。 1.参数说明&#xff1a; lower_case_table_names0 表名存储为给定的大小和比较是区分大小写的 lower_case_table_names 1 表名存储在磁盘是小写的&#xff0c;但是比较的时候是不区…

CMAKE生成exe文件时运行时有cmd窗口

1、运行exe执行文件 会有cmd弹窗 2、解决方法 只需要在cmakelists.txt中添加set(CMAKE_CXX_FLAGS “-mwindows”) 或者在cmake时指定编译参数cmake -DCMAKE_CXX_FLAGS"-mwindows"即可 如果用的是c而不是c&#xff0c;就只需把CXX改为C 重新编译打包运行后没有cmd弹…

centos自动同步北京时间

1、安装ntpdate服务 yum -y install ntpdate 2、加入自动任务计划 查找ntpdate的路径&#xff1a; which ntpdate 复制这个路径。 编辑自动任务计划并加入ntpdate&#xff1a; crontab -e # 每小时第30分钟同步AD域控时间 30 * * * * /usr/sbin/ntpdate -u 192.168.2.8 > …

超低成本FPGA JTAG方案

今天给大家带来一款超低成本的FPGA JTAG方案&#xff0c;硬件核心是用树莓派Pico&#xff0c;使用相关芯片自己制作JTAG则非常便宜&#xff0c;RP2040某宝的报价只有4元&#xff0c;所以自己制作成本非常低廉&#xff0c;当然使用Pico成本也不是很高&#xff0c;所以今天就以Pi…

ChineseChess

外卖中国象棋的梗。 外卖免单题&#xff1a; 如图&#xff0c;红棋先行&#xff0c;至少几步绝杀黑房&#xff08;黑房尽量不让自己输&#xff09;&#xff1f; ChineseChess.java 【帅】是左出还是右出&#xff0c;取决于&#xff0c;上图黑方那边的【士】 如图&#xff0c…

datax抽取库名带点的表遇到的问题

一、描述任务 使用Datax抽取mysql中的数据到hive的wedw_ods层中&#xff0c;mysql的库名为&#xff1a;b.p.n.p 表名为&#xff1a;bene_group 二、datax.json脚本生成 因为datax的脚本是自动生成的&#xff0c;生成的格式如下&#xff1a; {"core": {},"jo…

竞赛项目 深度学习手势识别算法实现 - opencv python

文章目录 1 前言2 项目背景3 任务描述4 环境搭配5 项目实现5.1 准备数据5.2 构建网络5.3 开始训练5.4 模型评估 6 识别效果7 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习手势识别算法实现 - opencv python 该项目较为新颖…

中国信息安全测评中心CISP家族认证一览

随着国家对网络安全的重视&#xff0c;中国信息安全测评中心根据国家政策、未来趋势、重点内容陆续增添了很多CISP细分认证。 今日份详细介绍&#xff0c;部分CISP及其子品牌相关认证内容&#xff0c;一定要收藏哟&#xff01; 校园版CISP NISP国家信息安全水平考试&#xff…

如何用SOLIDWORKS Simulation 避免共振现象

零件都有它的固有振动频率&#xff0c;称之为共振频率。当零部件的固有频率和激励频率相近时&#xff0c;对零部件的破坏是非常严重的&#xff0c;这就是我们说的共振。频率分析是设计师日常工作常见的设计验证。 今天给大家分享的是Simulation的频率分析操作方法&#xff1a; …

黑马头条项目学习--Day3: 自媒体文章发布

Day3: 自媒体文章发布 Day3: 自媒体文章发布1) 素材管理-图片上传a) 前期微服务搭建b) 具体实现 2) 素材管理-图片列表a) 接口定义b) 具体实现 3) 素材管理-照片删除/收藏a) 图片删除a1) 接口定义a2) 代码实现 b) 收藏与取消b1) 接口定义b2) 代码实现 4) 文章管理-频道列表查询…

前端面试自我介绍

前端面试自我介绍精选篇1 各位面试官大家好&#xff0c;我叫__&#xff0c;就读于__大学__学&#xff0c;大学本科学历&#xff0c;我的求职意向是与金融专业相关的职位&#xff0c;本人拥有较强的学习能力&#xff0c;能快速适应工作环境&#xff0c;兴趣爱好广泛&#xff0c…

nginx文件共享、服务状态和location模块的配置介绍

一.文件共享功能 1.清空html目录下文件并新建你要共享的文件 2.修改nginx.conf文件&#xff0c;开启autoindex功能 3.测试 二.状态模块 1.修改nginx.conf文件 2.测试 &#xff08;1&#xff09;使用刚才定义的IP/nginx_status进行访问 &#xff08;2&#xff09;status参…