leetcode LRU 缓存

leetcode: LRU 缓存

LRU 全称为 Least Recently Used,最近最少使用,常常用于缓存机制,比如 cpu 的 cache 缓存,使用了 LRU 算法。LRU 用于缓存机制时,关键的是当缓存满的时候有新数据需要加载到缓存的,这个时候需要淘汰谁的问题。

如下图所示,表示 LRU 算法的过程。假如有一个缓存,共有 4 个存储空间,按访问时间进行排序,最左边的存储空间存储的是最近访问的数据,最右边的存储空间存储的是最长时间没有访问的数据。

(1)一开始,缓存是空的,这个时候向缓存中放入一个数据 100,100 放到最左边的存储空间

(2)向缓存中放入一个数据 50,此时缓存有空余空间,所以将已有的数据向后移动,将 50 放到缓存的最左边

(3)向缓存中放入数据 500, 步骤与上一步相同

(4)向缓存中放入数据 1000,步骤与上一步相同

(5)读取数据 100,读取之后 100 就是最后访问的数据了,所以将 100 移到缓存的最左边,其它数据依次向后移动

(6)向缓存中放入数据 1,此时缓存是满的,所以需要先淘汰一个数据,从访问时间来看,最后一次访问 50 的间隔时间最长,也就是排在最右边的数据,所以将 50 淘汰,其它数据向后移动,将新数据 1 放入最左边的位置

如下是题目描述,题目的最后要求 get() 和 put() 的时间复杂度都要是 O(1) 的。使用数组来表示缓存难以满足 O(1) 的要求,因为在 put 或者 get 的时候,会引起数组数据的移动,数组中数据的移动时间复杂度是 O(n) 的。所以需要使用链表来表示缓存,当访问一个数据的时候需要将当前这个数据从原来的位置上删除,然后加到链表的头部,删除一个节点的话,需要将这个节点的前一个节点和下一个节点连接起来,如果使用单向链表的话,那么只能找到这个节点的下一个节点,找不到上一个节点,所以需要使用双向链表。

 

(1)使用双向循环链表来表示缓存

(2)为了满足时间复杂度是 O(1) 的要求,使用 data_addr_ 数组来保存节点的地址,数组的下标是 key,题目中说明了 key 的取值范围是 [0, 10000],所以可以使用一个数组来表示。使用 map 也不能保证时间复杂度是 O(1) 的,map 一般使用红黑树来实现,时间复杂度是 O(logn) 的。把数组的下标当 key,数组元素的值就是值,数组本省也可以当做一个简单的 map 来使用。

(3)当 put 数据时,要进行判断现在缓存是不是满了,如果满的话需要删除最久没有访问的数据,head_->next 保存最新访问的数据,head_->prev 保存最久没有访问的数据

struct Node {
    int key;
    int value;

    struct Node *next;
    struct Node *prev;
};

class LRUCache {
public:
    LRUCache(int capacity) {
      capacity_ = capacity;
      head_ = new Node();
      head_->next = head_;
      head_->prev = head_;
    }
    
    int get(int key) {
        Node *node = data_addr_[key];
        if (node == nullptr) {
            return -1;
        }

        ListUnLink(node);
        ListLinkHead(node);
        return node->value;
    }
    
    void put(int key, int value) {
      if (data_addr_[key] != nullptr) {       
        Node *node = data_addr_[key];
        ListUnLink(node);
        node->value = value;
        ListLinkHead(node);
      } else {
        Node *new_node = new Node();
        new_node->key = key;
        new_node->value = value;
        new_node->next = nullptr;
        new_node->prev = nullptr;

        if (count_ == capacity_) {
            Node *to_delete = head_->prev;
            ListUnLink(to_delete);
            data_addr_[to_delete->key] = nullptr;
            delete to_delete;
            count_--;
        }
        
        ListLinkHead(new_node);
        data_addr_[key] = new_node;
        count_++;
      }
    }

    void ListLinkHead(struct Node *ele) {
        ele->next = head_->next;
        ele->next->prev = ele;

        head_->next = ele;
        ele->prev = head_;
    }

    void ListUnLink(struct Node *ele) {
        ele->prev->next = ele->next;
        ele->next->prev = ele->prev;
    }

private:
    int capacity_ = 0;
    int count_ = 0;
    Node *data_addr_[10001] = {nullptr};
    struct Node *head_ = nullptr;
    
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

9.1 图片的分割处理(c++)

本文的图片处理分为图片分割、图像的亚像素坐标处理。亚像素处理的原理可以看论文一种基于多项式插值改进的亚像素细分算法,该论文的详解及c的代码实现可以看博文基于多项式插值的亚像素边缘定位算法_基于多项式插值的亚像素算法-CSDN博客。下面的内容很多来自以上博…

简单Mesh多线程合并,使用什么库性能更高

1)简单Mesh多线程合并,使用什么库性能更高 2)Unity Semaphore.WaitForSignal耗时高 3)VS编辑的C#代码注释的中文部分乱码 4)变量IntPtr m_cachePtr切换线程后变空 这是第389篇UWA技术知识分享的推送,精选了…

Stability AI最新的SD3模型存在严重问题 为规避裸体结果导致躯体部分错乱

人工智能 Stability AI 最新的 SD3 Medium 模型存在严重问题,只要生成人物就会出现躯体错乱,这似乎是该公司刻意规避生成裸体图片的结果。目前猜测他们可能在训练过程中就剔除了 NSFW 内容,同时在训练时规避裸体内容进而导致模型也会刻意将人…

03 Tricks

一:Auto-ML的一般形式 还可以支持这个CV啦lp啦,还有多模态啦,都还有很多很多任务啊,都可以支持啊 Auto-Sklearn Auto-Pytorch 结构搜所:神经网络搜所算法: AutoGluon 02 >自动特征工程 Tsfresh Boru…

ATF是如何完成双系统切换的?

ATF(Arm Trusted Firmware)是一个用于ARM架构处理器的可信固件,它最初提供的最主要的功能就是:双系统切换和电源管理。 那么如何进行双系统切换呢,在双系统切换的示例中,除了CPU的跳转,例如CPU…

用Rust手把手编写一个Proxy(代理), 开始动工

https://shop.kongfz.com/795263/ 代理端和代理服务端之间可用自有格式来实现多路复用以减少连接的建立断开的开销,目前暂未实现代理服务端。 类结构 proxy.rs 负责代理结构的存储,监听类型,监听地址,是否有父级地址,认证账号密码等。 flag.rs 监听类型的二进制结构,…

2024 年最新 Python 基于百度智能云实现短语音识别、语音合成详细教程

百度智能云语音识别 采用国际领先的流式端到端语音语言一体化建模算法,将语音快速准确识别为文字,支持手机应用语音交互、语音内容分析、机器人对话等场景。百度短语音识别可以将 60 秒以下的音频识别为文字。适用于语音对话、语音控制、语音输入等场景…

金融行业的等保测评要求

在金融行业中,网络安全问题非常普遍,如恶意攻击、病毒感染、数据泄露等。这些问题可能会导致金融机构的信息系统瘫痪,造成巨大的经济损失,甚至影响国家金融稳定。因此,金融机构应该高度重视网络安全问题,采…

微软的反面:错过了AI时代最大机遇的亚马逊

内容提要 一度被亚马逊给予厚望的Alexa为何被后来者ChatGPT吊打,错失争霸AI世界的机会?这里面不仅有技术的锅。 文章正文 在AI浪潮席卷全球之际,科技巨头们无不争先恐后,力图抢占先机。然而,就在微软借助ChatGPT一举…

彻底理解 C 语言的数组在内存中到底是怎么存放的!

在C语言中,数组是经常被用到的重要数据类型,但在实际使用时,往往有很多工程师会出现各种各样的问题,如内存越界、错误的访问、初始化不当等。这其中有很大一个原因是没有彻底理解数组的存储机制,出现了一些非法地址或者…

Pytorch解决 多元回归 问题的算法

Pytorch解决 多元回归 问题的算法 回归是一种基本的统计建模技术,用于建立因变量与一个或多个自变量之间的关系。 我们将使用 PyTorch(一种流行的深度学习框架)来开发和训练线性回归模型。 二元回归的简单示例 训练数据集(可获取&…

微信群发机器人.使用指南.

0.简介 1.介绍 微信群发机器人是用来群发微信消息的工具,通过控制电脑的键盘和鼠标操作微信app来实现群发.支持的消息类型有:文字,图片,视频,文件,小程序,位置等. 群发机器人也可以将微信联系人中的信息保存到电脑csv表格中,以供分析. 因其是通过模拟用户操作鼠标键盘来实现群…

如何在 Vue 3 中使用 vue3-print-nb 实现灵活的前端打印

你好,我是小白Coding日志,一个热爱技术的程序员。在这里,我分享自己在编程和技术世界中的学习心得和体会。希望我的文章能够给你带来一些灵感和帮助。欢迎来到我的博客,一起在技术的世界里探索前行吧! 前言 在前端开…

go interface

package mainimport "fmt"// 接口 interface func main() {c : Chinese{} //创建一个中国人实例u : American{} //创建一个美国人实例greet(c) //中国人打招呼greet(u) //美国人打招呼 }// 接收具备SayHello接口能力的变量 func greet(s SayHello) {…

KOL营销策略:危机公关中的品牌修复与形象重塑

在当今数字化时代,品牌声誉的管理和维护愈发重要。危机公关作为品牌管理的重要一环,对于企业的长期生存和发展具有至关重要的影响。而KOL作为具有强大影响力和号召力的个体,在危机公关中扮演着不可或缺的角色。本文Nox聚星将和大家探讨KOL在危…

yolo案例项目学习记录

box-ocr: 监控摄像头视频流实时计数传送带的货物,并提取货物上面文字或二维码 1.本地环境: 1.1torch、torchvison、torchaudio版本对应关系 PyTorch中torch、torchvision、torchaudio、torchtext版本对应关系_torch2.0.1对应的torchvision-CSDN博客 1…

Leetcode419. 甲板上的战舰

Every day a Leetcode 题目来源:419. 甲板上的战舰 解法1:一次遍历 战舰的个数,等于战舰「头部」的个数。 具体来说,如果位于 (i, j) 的格子是战舰的头部,那么左边和上边的相邻格子不能是 X。 代码: …

php收银系统源码推荐

智慧新零售系统是一套线下线上一体化的收银系统。致力于给零售门店提供『多样化线下收银』、『ERP进销存』、『o2o小程序商城』、『精细化会员管理』、『丰富营销插件』等一体化行业解决方案! 一、多样化线下收银 1.聚合收款码 ①适用商户:小微门店&am…

Vue40-vueComponent构造函数

一、组件的本质:VueComponent构造函数 组件的本质是:构造函数 二、每一次调用vue.extend,返回的事一个全新的 VueComponent VueComponent的源码如下: 三、组件中的this 组件中的this是VueComponent实例对象,结构和vm…

想学编程,什么语言最好上手?

Python是许多初学者的首选,因为它的语法简洁易懂,而且有丰富的资源和社区支持。我这里有一套编程入门教程,不仅包含了详细的视频 讲解,项目实战。如果你渴望学习编程,不妨点个关注,给个评论222,…