实习冲刺第二十八天

news2024/11/24 8:31:38

146.LRU缓存

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

思路详解:

我们使用双向链表和哈希表来联合解决这个问题,哈希表的键必须不是重复的,而且操作哈希表的时间复杂度为O(1),哈希表负责记录键和节点的映射关系,双向链表负责存储和修改数据,这里所有新加入的元素都会被重新置于双向链表的头,所有太久未被访问的元素都会置于链表尾部,通过查询并删除尾部节点就可以实现最近最少使用的办法。

代码详解:

struct Node{
    int key,val;
    Node*prev,*next;
    Node():key(0),val(0),prev(nullptr),next(nullptr){}
    Node(int keys,int vals):key(keys),val(vals),prev(nullptr),next(nullptr){}
};//构建一个双向链表的结构体,它包括链表的前驱,后继,构造函数,初始化键值的构造函数

class LRUCache {
public:
    Node*head,*tail;
    unordered_map<int,Node*> un_map;
    int capacity,size;//定义链表的虚拟头尾节点,节点和key的哈希映射,当前容量和总容量
    LRUCache(int _capacity):capacity(_capacity),size(0)
    {
        head=new Node();//初始化头尾节点,并让他们连接起来
        tail=new Node();
        head->next=tail;
        tail->prev=head;    
    }
    
    int get(int key) {
        if(!un_map.count(key))//count函数用以查询哈希表中是否有对应的键,哈希表中的键值是不重复的
        {
            return -1;
        }
        Node*node=un_map[key];
        removeNode(node);//查询缓存的时候将被查询的元素移除并重新插入回头节点
        insertNode(node);//此方法被视为使用缓存中的数据,所以我们将它更新
        return node->val;
    }
    
    void put(int key, int value) {
        if(un_map.count(key))//如果存在修改值,并更新使用时间
        {
            Node*node=un_map[key];
            node->val=value;
            removeNode(node);
            insertNode(node);
        }
        else
        {
            if(size>=capacity)//不存在的话先看使用内存是否已满,已满就移除最后一个元素
            {
                Node*remove=tail->prev;//获取要被移除的节点
                un_map.erase(remove->key);//从哈希表中移除
                removeNode(remove);//从链表中移除
                size--;//已使用大小减一
            }
            Node*node=new Node(key,value);
            insertNode(node);
            un_map[key]=node;
            size++;
        }
    }
    void removeNode(Node*node)//方法,用于删除链表中节点
    {
        node->prev->next=node->next;//当前节点前驱的后继指向当前节点的后继
        node->next->prev=node->prev;//当前节点后继的前驱指向当前节点的前驱
    }
    void insertNode(Node*node)//方法,用于插入元素至链表的头
    {
        node->prev=head;//当前节点的前驱是虚拟头节点
        node->next=head->next;//当前元素的后继是虚拟头节点的后继
        head->next->prev=node;//虚拟头节点的前驱是当前节点
        head->next=node;//头节点的下一个节点是当前节点
    }
};

面经:

1. 移动语义和拷贝语义有什么区别

  • 拷贝语义会创建资源的副本。
  • 移动语义会转移资源的所有权。
  • 拷贝语义可能会引起较大的性能开销,尤其是涉及到大型数据结构时。
  • 移动语义通常能提供更好的性能,因为它避免了不必要的数据复制。
  • 在拷贝后,原对象保持不变。
  • 在移动后,原对象可能不再可用或处于未定义状态。

2. 什么是智能指针,都有哪些智能指针 

  • C++11标准库引入了智能指针,它们是模板类,用于自动管理动态分配的内存,从而减少内存泄漏和其他资源管理错误的风险。智能指针确保资源在适当的时机被自动释放。

智能指针包括以下三种:

  • unique_ptr

独占型智能指针,它保证同一时间只有一个指针指向所管理的对象。

当unique_ptr 被销毁时,它所管理的对象也会被自动销毁。

unique_ptr 不支持拷贝操作,但可以通过 move 将所有权转移给另一个unique_ptr。

  • shared_ptr

共享型的智能指针,它允许多个指针共享同一个对象。

它使用引用计数机制来跟踪有多少个 shared_ptr 共享同一个对象。当最后一个shared_ptr 被销毁时,对象也会被自动销毁。shared_ptr 支持拷贝和赋值操作。

  • weak_ptr:

弱引用智能指针,它用于解决 shared_ptr 可能造成的循环引用问题。

weak_ptr 必须配合 shared_ptr 使用,它不会增加引用计数。

当需要访问对象时,可以尝试通过weak_ptr 的 lock 方法来获取 shared_ptr,如果对象已经被销毁,则 lock 方法会返回一个空的shared_ptr。

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

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

相关文章

Bugku CTF_Web——my-first-sqli

Bugku CTF_Web——my-first-sqli 进入靶场 随便输一个看看 点login没有任何回显 方法一&#xff1a; 上bp抓包 放到repeter测试 试试万能密码&#xff08;靶机过期了重新开了个靶机&#xff09; admin or 11--shellmates{SQLi_goeS_BrrRrRR}方法二&#xff1a; 拿包直接梭…

BUUCTF—Reverse—easyre(1)

非常简单的逆向 拿到exe文件先查下信息&#xff0c;是一个64位程序&#xff0c;没有加壳&#xff08;壳是对代码的加密&#xff0c;起混淆保护的作用&#xff0c;一般用来阻止逆向&#xff09;。 然后拖进IDA(64位)进行反汇编 打开以后就可以看到flag flag{this_Is_a_EaSyRe}

全面击破工程级复杂缓存难题

目录 一、走进业务中的缓存 &#xff08;一&#xff09;本地缓存 &#xff08;二&#xff09;分布式缓存 二、缓存更新模式分析 &#xff08;一&#xff09;Cache Aside Pattern&#xff08;旁路缓存模式&#xff09; 读操作流程 写操作流程 流程问题思考 问题1&#…

React基础知识一

写的东西太多了&#xff0c;照成csdn文档编辑器都开始卡顿了&#xff0c;所以分篇写。 1.安装React 需要安装下面三个包。 react:react核心包 react-dom:渲染需要用到的核心包 babel:将jsx语法转换成React代码的工具。&#xff08;没使用jsx可以不装&#xff09;1.1 在html中…

Vue3中使用:deep修改element-plus的样式无效怎么办?

前言&#xff1a;当我们用 vue3 :deep() 处理 elementui 中 el-dialog_body和el-dislog__header 的时候样式一直无法生效&#xff0c;遇到这种情况怎么办&#xff1f; 解决办法&#xff1a; 1.直接在 dialog 上面增加class 我试过&#xff0c;也不起作用&#xff0c;最后用这种…

鸿蒙进阶-状态管理

大家好啊&#xff0c;这里是鸿蒙开天组&#xff0c;今天我们来学习状态管理。 开始组件化开发之后&#xff0c;如何管理组件的状态会变得尤为重要&#xff0c;咱们接下来系统的学习一下这部分的内容 状态管理机制 在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&a…

leetcode:129. 求根节点到叶节点数字之和

给你一个二叉树的根节点 root &#xff0c;树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表一个数字&#xff1a; 例如&#xff0c;从根节点到叶节点的路径 1 -> 2 -> 3 表示数字 123 。 计算从根节点到叶节点生成的 所有数字之和 。…

(南京观海微电子)——GH7006+BOE2.6_GV026WVQ-N81-1QP0_800RGB480_MIPI_LVDS_RGB原理介绍

1. 原理介绍 2. 代码 // Model - GV026WVQ-1QP0 // IC - GH7006 // Width - 800 // Height - 480 // REV: - V01 // DATA - 20240507 // INTERFACE- MIPI //"Vfp" value"16" /> //"…

速度革命:esbuild如何改变前端构建游戏 (1)

什么是 esbuild&#xff1f; esbuild 是一款基于 Go 语言开发的 JavaScript 构建打包工具&#xff0c;以其卓越的性能著称。相比传统的构建工具&#xff08;如 Webpack&#xff09;&#xff0c;esbuild 在打包速度上有着显著的优势&#xff0c;能够将打包速度提升 10 到 100 倍…

Excel的图表使用和导出准备

目的 导出Excel图表是很多软件要求的功能之一&#xff0c;那如何导出Excel图表呢&#xff1f;或者说如何使用Excel图表。 一种方法是软件生成图片&#xff0c;然后把图片写到Excel上&#xff0c;这种方式&#xff0c;因为格式种种原因&#xff0c;导出的图片不漂亮&#xff0c…

自动化运维-Linux通用性日志切割脚本

一、公司提供的参考脚本&#xff1a; #!/bin/bash # 定义需要清理的文件 log_file("/mpjava/ly.mp.dfpv.acc.biz/bin/nohup.out""/mpjava/ly.mp.dfpv.acc.service/bin/nohup.out"# 添加更多微服务的日志目录路径 ) # 获取当天日期 date_now$(date %Y%m%d)…

Let‘s Encrypt SSL证书:acmessl.cn申请免费3个月证书

目录 一、CA机构 二、Lets Encrypt特点 三、申请SSL 一、CA机构 ‌Lets Encrypt‌是一个由非营利组织Internet Security Research Group (ISRG)运营的证书颁发机构&#xff08;CA&#xff09;&#xff0c;旨在通过自动化和开放的方式为全球网站提供免费、可靠的SSL/TLS证书。…

Java连接MySQL数据库进行增删改查操作

Test 1 首先去查看一下MySQL的版本&#xff1a;mysql -V&#xff08;在cmd中&#xff09;记得要启动MySQL服务在cmd中验证是否可以登录数据库成功&#xff1a;mysql -u root -p&#xff08;然后输入密码&#xff1a;root&#xff09;Test 2 在IDEA创建项目在SQLyog中创建数据…

从搭建uni-app+vue3工程开始

技术栈 uni-app、vue3、typescript、vite、sass、uview-plus、pinia 一、项目搭建 1、创建以 typescript 开发的工程 npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project2、安装sass npm install -D sass// 安装sass-loader&#xff0c;注意需要版本10&#xff0c;…

React (三)

文章目录 项目地址十二、性能优化12.1 使用useMemo避免不必要的计算12.2 使用memo缓存组件,防止过度渲染12.3 useCallBack缓存函数12.4 useCallBack里访问之前的状态(没懂)十三、Styled-Components13.1 安装13.2给普通html元素添加样式13.3 继承和覆盖样式13.4 给react组件添…

javascrip页面交互

元素的三大系列 offset系列 offset初相识 offset系列属性 作用 element.offsetParent 返回作为该元素带有定位的父级元素&#xff0c;如果父级没有定位&#xff0c;则返回body element.offsetTop 返回元素相对于有定位父元素上方的偏移量 element.offsetLeft 返回元素…

生成对抗网络(简要介绍)

生成对抗网络&#xff08;Generative Adversarial Network&#xff0c;GAN&#xff09;是一种深度学习模型架构&#xff0c;由 Ian Goodfellow 等人在 2014 年提出。GAN 由两个神经网络组成——生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&…

(C语言)文件操作

目录 文件 程序文件 数据文件 文件名 ​编辑数据文件的分类 文件的打开和关闭 流 标准流 1&#xff09;stdin 2&#xff09;stdout 3&#xff09;stderr 文件指针 文件的打开和关闭 对文件内容操作的函数 1&#xff09;fgetc&#xff0c;fputc 2&#xff09;fp…

招商蛇口|在低密园林里,开启生活的“任意门”

“最好的建筑是这样的&#xff0c;我们深处在其中,却不知道自然在哪里终了&#xff0c;艺术在哪里开始。” 凭借深耕西安10载的城市远见&#xff0c;以及建立在成功人居经验之上的敏锐洞察&#xff0c;招商蛇口将林语堂名言里的生活&#xff0c;变成了现实。 都市化越是加速&…

【es6进阶】vue3中的数据劫持的最新实现方案的proxy的详解

vuejs中实现数据的劫持,v2中使用的是Object.defineProperty()来实现的&#xff0c;在大版本v3中彻底重写了这部分&#xff0c;使用了proxy这个数据代理的方式&#xff0c;来修复了v2中对数组和对象的劫持的遗留问题。 proxy是什么 Proxy 用于修改某些操作的默认行为&#xff0…