首页 > 编程语言 >LRU(最近最少使用) 缓存题与该算法思路

LRU(最近最少使用) 缓存题与该算法思路

时间:2023-06-18 18:12:50浏览次数:51  
标签:map 缓存 int 元素 list 算法 LRU key cacheData

题:https://leetcode.cn/problems/lru-cache/description/

请你设计并实现一个满足 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) 的平均时间复杂度运行。

解题(题解说明见注释)

/*
采用hash map和list结合方式,让hash map达到O(1)的访问性能,让list根据元素的顺序实现最近访问的过程。
思路:
1. 每次读或写元素,表示该元素最近被访问了,则把该元素移动至List队首,这样能保证第一个元素是最近访问的,最后一个元素是最近最少访问的。
2. 如果新增的元素数量大于设置的容量,则每次直接删除最后一个元素即可,实现了最近最少使用则清除的要求。
3. 若只用list查找性能太差,则使用哈希map存放key-list元素指针的方式,实现能直接访问List元素的目的,达到o(1)的时间复杂度。

*/
class LRUCache {
public:
    LRUCache(int capacity) : capacity(capacity) {

    }
    
    int get(int key) {
        auto map_it = cacheMap.find(key);
        if (map_it != cacheMap.end()) {
            // 如果找到了,则把元素移动到队首表示最近访问过,并返回value
            cacheData.splice(cacheData.begin(), cacheData, map_it->second);
            return map_it->second->second;
        }
        return -1;

    }
    
    void put(int key, int value) {
        auto map_it = cacheMap.find(key);
        // 如果找到了则更新value
        if (map_it != cacheMap.end()) {
            // 更新过值也表示最近访问过,需把该元素移动到队首
            cacheData.splice(cacheData.begin(), cacheData, map_it->second);
            map_it->second->second = value;
            return;
        }
        // 如果没有找到,则新建一元素节点,放在队首
        cacheData.emplace_front(key, value);
        cacheMap[key] = cacheData.begin();
        // 如果超过了容量,则把队尾一直没被访问过的元素删除了
        if(cacheMap.size() > capacity) {
            cacheMap.erase(cacheData.back().first);
            cacheData.pop_back();
        }

    }
private:
    int capacity;
    // cacheData存放的是一个元素pair,一个pair是<key, value>的结对,
    // 要同时存key的原因是需要在删除元素时知道这个元素的key,才能保证删除元素也是O(1)
    std::list<std::pair<int, int>> cacheData;
    // key对于一个List元素节点,通过该元素的迭代器指针能直接找到list元素,以免List每次从头遍历耗时
    unordered_map<int, std::list<std::pair<int, int>>::iterator> cacheMap;
};

 /*
 list.splice() 将一个List的元素移动到当前list的指定位置,如:
 list1.splice(p1, list2, p2)是将list2中p2指向的节点移动到list1的p1之前,
 完成后list2中不再有p2,单纯的指针赋值,不会进行(移动)构造析构等操作。
 如果是list1.splice(p1, list1, p2)则是对list1自己的元素调整顺序,须得p2移动到p1前边。

 list.splice()有三个重载:
 1. void splice (iterator position, list& x);	移动整个list
 2. void splice (iterator position, list& x, iterator i);	移动单个元素
 3. void splice (iterator position, list& x, iterator first, iterator last);	移动指定范围的元素

 */

注:题解思路来源于题评论

标签:map,缓存,int,元素,list,算法,LRU,key,cacheData
From: https://www.cnblogs.com/UFO-blogs/p/17489432.html

相关文章

  • 算法练习-day10
    栈和队列20.有效的括号题意:给定一个只包括'(',')','{','}','[',']' 的字符串s,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号示例:    思路:本题我有两种思路,1.双栈存储:我们可......
  • 算法题总结-吃苹果(有序处理)
    原题https://leetcode.cn/problems/maximum-number-of-eaten-apples/有一棵特殊的苹果树,一连n天,每天都可以长出若干个苹果。在第i天,树上会长出apples[i]个苹果,这些苹果将会在days[i]天后(也就是说,第i+days[i]天时)腐烂,变得无法食用。也可能有那么几天,树上不会长出新的......
  • TensorFlow05.3 神经网络反向传播算法-多层感知机梯度(理论知识)
    首先这个是链式法则:如果扩展到多层感知机的话:我们在学这个的时候首先知道一个东西:所以这个整体的步骤就是:1.2.3.......
  • 代码随想录算法训练营第十天| 20. 有效的括号 1047. 删除字符串中的所有相邻重复项
    20.有效的括号  特点:左括号之后,可能还会有左括号,但是只要有右括号,那么它必须立刻和最近的左括号代码:1charreturnRightChar(char&c)2{3switch(c)4{5case'[':return']';6case'(':return')';7case'{':r......
  • TensorFlow05.3 神经网络反向传播算法-链式法则
    1BasicRule2Productrule3QuotientRule4Chainrule(链式法则)在这个神经网络中:......
  • TensorFlow05.2 神经网络反向传播算法-单输出感知机和多输出感知机及其梯度
    1单输出感知机在这里我们可以看到,\(W_2,1^1\)其中他的下标第一个2,表示的连着上一层的x2,下标第一个1代表着连着下一侧的x1。然后上标1代表着第一层。E是做了一个loss处理。\(X_i^1\)这个下标的i代表当前层数节点的编号,然后这个1代表着第1层。\(W_i,j^k\),i表示上一层的节点编......
  • 算法刷题记录:AcWing 4908. 饥饿的牛
    目录题目链接:题目分析:时间复杂度SF代码AC代码:题目链接:https://www.acwing.com/problem/content/description/4911/题目分析:数据范围最大\(10^{14}\),所以如果采用枚举一定会TLE,因为只有\(10^5\)天会运来新的草,所以我们可以只考虑运草的天。假设当前到\(d_2\)天之前剩余干......
  • 分布式、负载均衡、缓存、数据库中间件【杭州多测师_王sir】
      ......
  • 【技术积累】算法中的排序算法【一】
    冒泡排序(BubbleSort)算法描述:通过不断地交换相邻两个元素,把最大的元素移到数组的最后面,然后不断缩小排序范围,直到整个数组有序。算法步骤:遍历整个待排序的数组。比较相邻的两个元素。如果前面的元素比后面的元素大,就交换它们重复以上步骤,直到整个数组有序。伪代码:proced......
  • 算法设计
    公司计划面试2N人。第i人飞往A市的费用为costs[i][0],飞往B市的费用为costs[i][1]。返回将每个人都飞到某座城市的最低费用,要求每个城市都有N人抵达。示例:输入:[[10,20],[30,200],[400,50],[30,20]](第i个人飞往两个城市的费用)输出:110假设你是黄牛,用贪心算法找到月饼的最......