面试题常考:LRU缓存

这篇具有很好参考价值的文章主要介绍了面试题常考: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 ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 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.题目中存放的数据是键值对形式的,所以我们可以采用哈希表(unordered_map)来实现

2.同时,题目要求get()、put()的时间复杂度为O(1),也就是能够快速插入、删除元素,来确保时间复杂度低,最佳的数据结构应该是链表,这里用双向链表最高效

所以,我们需要添加一个双向链表的结构体和无序map来对数据实现LRU缓存。

详细过程参考下面代码:

Code:文章来源地址https://www.toymoban.com/news/detail-699164.html

class LRUCache {
public:
	//双链表的结构体
    struct Node
    {
        int key;
        int val;
        //前驱和后继指针
        Node * prev,*next;
        //构造函数
        Node():key(0),val(0),prev(nullptr),next(nullptr){}
        Node(int m_key,int m_val):key(m_key),val(m_val),prev(nullptr),next(nullptr){}
    };
    unordered_map<int,Node*> map;//哈希表,用来存储键值对
    Node* head;//头节点
    Node* tail;//尾节点
    
    int m_capacity;//总容量
    int size;//哈希表当前容量
    LRUCache(int capacity):m_capacity(capacity),size(0) {
        //初始化头尾节点
        head=new Node();
        tail=new Node();
        //构建双向链表
        head->next=tail;
        tail->prev=head;
    }
    //获取函数
    int get(int key) {
        //如果哈希表中不存在键为key,直接返回-1
        if(!map.count(key))
        {
            return -1;
        }
        //存在key
        //获取链表的节点
        Node* node=map[key];
        remove(node);//删除节点
        AddNodeToHead(node);//将当前节点移至头节点之后
        return node->val;//返回节点的值
    }
    
    void put(int key, int value) {
        //如果当前key值已存在
        if(map.count(key))
        {
            //获取节点
            Node* node=map[key];
            //改变节点的值为新的value
            node->val=value;
            remove(node);//删除节点
            AddNodeToHead(node);//将节点移至头节点之后
        }
        //不存在,则加入到哈希表中
        else
        {
            //判断容量是否已满
            if(size==m_capacity)//满了
            {
                //获取最近最久未使用的节点,也就是尾节点的前驱节点
                Node* removed=tail->prev;
                //从哈希表中移除该节点
                map.erase(removed->key);
                //删除节点
                remove(removed);
                //当前容量--
                size--;
            }
            //创建新节点
            Node* node=new Node(key,value);
            AddNodeToHead(node);//将节点移至头节点之后
            map[key]=node;//加入哈希表中
            size++;//当前容量++
        }
    }
    //删除节点函数
    void remove(Node* node)
    {
        node->prev->next=node->next;
        node->next->prev=node->prev;
    }
    //将节点移至头节点之后
    void AddNodeToHead(Node* node)
    {
        node->prev=head;
        node->next=head->next;
        head->next->prev=node;
        head->next=node;
    }
};

到了这里,关于面试题常考:LRU缓存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构(五):哈希表及面试常考的算法

    哈希表,也叫散列表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。例如,下列键(key)为人名,value为性别。 数组 map(映射) 映射 底层实现 是否有序 数值是否可以重复 能否更改数

    2024年02月05日
    浏览(48)
  • 初识Go语言25-数据结构与算法【堆、Trie树、用go中的list与map实现LRU算法、用go语言中的map和堆实现超时缓存】

      堆是一棵二叉树。大根堆即任意节点的值都大于等于其子节点。反之为小根堆。   用数组来表示堆,下标为 i 的结点的父结点下标为(i-1)/2,其左右子结点分别为 (2i + 1)、(2i + 2)。 构建堆   每当有元素调整下来时,要对以它为父节点的三角形区域进行调整。 插入元素

    2024年02月12日
    浏览(57)
  • leetcode 146. LRU 缓存

             本题核心就是要将map中,最近最少操作的那个key给剔除掉,于是我们可以使用双端链表LinkedList 来维护每个元素的操作情况,最近操作的元素就将其移至表头,越久没操作的元素,自然就会沉到表尾。  一旦缓存满了,将表尾元素剔除即可。  java代码如下:

    2024年02月08日
    浏览(42)
  • LeetCode刷题---LRU缓存

    LRU是Least Recently Used的缩写,即最近最少使用,是一种内存管理算法,也可以用作缓存淘汰策略。 这种算法的核心思想是:如果数据最近被访问过,那么将来被访问的几率也更高。 因此,当内存或缓存容量有限,需要淘汰部分数据时,LRU算法会优先淘汰那些最长时间未被访问

    2024年02月22日
    浏览(37)
  • 【LeetCode】146.LRU缓存

    请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。 实现  LRUCache  类: LRUCache(int capacity)  以  正整数  作为容量  capacity  初始化 LRU 缓存 int get(int key)  如果  key  存在于缓存中,则返回的值,否则返回  -1  。 void put(int key, int value)  如果

    2024年02月09日
    浏览(41)
  • 【LeetCode-中等题】146. LRU 缓存

    LRU缓存是什么:LRU缓存机制,你想知道的这里都有 实现 LRU 缓存算法 map —key存 integer value存链表节点 ListNode 存 next 和prev 引用 以及 存 key 和value 具体值 图解:官方图解 步骤: 定义一个自定义的双向链表节点类 DLinkedNode,该类包含 key 和 value 字段,并且具有 prev 和 next 指针

    2024年02月10日
    浏览(48)
  • 【LeetCode刷题-链表】--146.LRU缓存

    方法一:哈希表+双向链表 使用一个哈希表和一个双向链表维护所有在缓存中的键值对 双向链表按照被使用的顺序存储了这些键值对,靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久使用的 哈希表即为普通的哈希映射,通过缓存数据的键映射到其在双向链表中的

    2024年02月05日
    浏览(44)
  • leetcode做题笔记146. LRU 缓存

    请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。 实现  LRUCache  类: LRUCache(int capacity)  以  正整数  作为容量  capacity  初始化 LRU 缓存 int get(int key)  如果  key  存在于缓存中,则返回的值,否则返回  -1  。 void put(int key, int value)  如果

    2024年02月07日
    浏览(36)
  • Leetcode 146. LRU 缓存(Hashmap+双链表)

    请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: ● LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 ● int get(int key) 如果 key 存在于缓存中,则返回的值,否则返回 -1 。 ● void put(int key, int value) 如果 key 已

    2024年02月16日
    浏览(47)
  • 【leetcode100-035】【链表/哈希链表】LRU缓存

    【题干】 请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。 实现  LRUCache  类: LRUCache(int capacity)  以  正整数  作为容量  capacity  初始化 LRU 缓存 int get(int key)  如果  key  存在于缓存中,则返回的值,否则返回  -1  。 void put(int key, in

    2024年02月01日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包