[LeetCode] LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

解题思路

Cache(高速缓存),需实现随机存取操作和高效的插入删除操作。

  • vector可以高效的随机存取,但是在插入删除会造成内存块的拷贝。另外,当内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝。
  • list可以高效的插入删除,但是不支持随机存取。
  • deque支持随机存取,但是只能在两端进行插入删除操作。

因此采用双向链表来实现插入删除操作,同时采用哈希表来实现高效的随机存取。在unordered_map<key, value>中,key表示键值,value存储该键值在链表中所对应的结点位置。

实现代码1

/*****************************************************************
    *  @Author   : 楚兴
    *  @Date     : 2015/2/16 17:52
    *  @Status   : Accepted
    *  @Runtime  : 176 ms
******************************************************************/
#include <iostream>
#include <list>
#include <unordered_map>

using namespace std;

struct cacheNode
{
    int key;
    int value;
    cacheNode(int k, int v) : key(k), value(v) {}
};
class LRUCache{
public:
    LRUCache(int capacity) {
        size = capacity;
    }

    int get(int key) {
        if (cacheMap.find(key) != cacheMap.end())
        {
            cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
            return cacheList.begin()->value;
        }
        else
        {
            return -1;
        }
    }

    void set(int key, int value) {
        if (cacheMap.find(key) != cacheMap.end())
        {
            cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
            cacheList.begin()->value = value;
            cacheMap[key] = cacheList.begin();
        }
        else
        {
            if (cacheList.size() == size)
            {
                cacheMap.erase(cacheList.back().key);
                cacheList.pop_back();
            }
            cacheList.push_front(cacheNode(key, value));
            cacheMap[key] = cacheList.begin();
        }
    }
public:
    int size;
    list<cacheNode> cacheList;
    unordered_map<int, list<cacheNode>::iterator> cacheMap;
};

void print(LRUCache cache)
{
    for (auto it = cache.cacheList.begin(); it != cache.cacheList.end(); it++)
    {
        cout<<"key:"<<it->key<<"\tvalue:"<<it->value<<endl;
    }
    cout<<endl;
}

int main()
{
    LRUCache cache(4);
    cache.set(1,2);
    cache.set(2,3);
    cache.set(3,4);
    cache.set(4,5);

    print(cache);
    cache.set(2,5);
    cache.set(3,100);
    cache.set(10,45);
    cache.set(10,456);
    print(cache);

    return 0;
}

琢摸着感觉上述代码效率还是偏低,于是把cache结点由一个struct结构体改为了一个pair,但是经过测试效果相当。以下是第二个版本的代码:

实现代码2

class LRUCache{
public:
    LRUCache(int capacity) {
        size = capacity;
    }

    int get(int key) {
        if (cacheMap.find(key) != cacheMap.end())
        {
            cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
            return cacheList.begin()->second;
        }
        else
        {
            return -1;
        }
    }

    void set(int key, int value) {
        if (cacheMap.find(key) != cacheMap.end())
        {
            cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);
            cacheList.begin()->second = value;
            cacheMap[key] = cacheList.begin();
        }
        else
        {
            if (cacheList.size() == size)
            {
                cacheMap.erase(cacheList.back().first);
                cacheList.pop_back();
            }
            cacheList.push_front(make_pair(key, value));
            cacheMap[key] = cacheList.begin();
        }
    }
private:
    int size;
    list<pair<int, int>> cacheList;
    unordered_map<int, list<pair<int,int>>::iterator> cacheMap;
};
时间: 2024-11-24 00:05:19

[LeetCode] LRU Cache的相关文章

LeetCode: LRU Cache 最近最少使用算法 缓存设计

设计并实现最近最久未使用(Least Recently Used)缓存.   题目描述: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key

LRU Cache

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(

哪个Map最适合用来实现LRU Cache?

问题描述 前段时间面试碰到的一道题,最近进了这家公司了,再拿出来看看.求大神继续解脱.30.下面哪个Map最适合用来实现LRUCache?A.HashtableB.TreeMapC.HashMapD.IdentityHashMapE.WeakHashMap网上给的答案是A.为什么?大家一般如何实现这个最近最少使用cache? 解决方案 解决方案二:就那几个可选的来说只能是A了因为是线程安全的不过个人认为应该用Mapmap=Collections.synchronizedMap(newLinked

Redis作为LRU Cache的实现

公有云Redis服务:https://www.aliyun.com/product/kvstore?spm=5176.8142029.388261.37.59zzzj 背景 Redis作为目前最流行的KV内存数据库,也实现了自己的LRU(Latest Recently Used)算法,在内存写满的时候,依据其进行数据的淘汰.LRU算法本身的含义,这里不做赘述,严格的LRU算法,会优先选择淘汰最久没有访问的数据,这种实现也比较简单,通常是用一个双向链表+一个哈希表来实现O(1)的淘汰和更新操作.但

C++友元函数的问题求大神解答

问题描述 C++友元函数的问题求大神解答 1:友元函数在定义时括号内的&有啥用 2:友元函数怎么利用类中的函数的返回值 初学者帮忙解答一下!谢谢 解决方案 1 .和普通函数一样,带&是引用,也就是函数内可以修改实参. 2.因为引用做形参,可以修改实参,所以要使用函数返回值,直接调用函数就可以了 解决方案二: 和普通函数一样,带&是引用,也就是函数内可以修改实参. 要使用函数返回值,直接调用函数就可以了. 解决方案三: 求大神帮解答javaEE这个问题,谢谢了liunx 串口通信问题

浅析LRU(K-V)算法缓存教程

LRU(Least Recently Used)算法是缓存技术中的一种常见思想,顾名思义,最近最少使用,也就是说有两个维度来衡量,一个是时间(最近),一个频率(最少).如果需要按优先级来对缓存中的K-V实体进行排序的话,需要考虑这两个维度,在LRU中,最近使用频率最高的排在前面,也可以简单的说最近访问的排在前面.这就是LRU的大体思想. 在操作系统中,LRU是用来进行内存管理的页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间

LeetCode总结【转】

转自:http://blog.csdn.net/lanxu_yy/article/details/17848219 版权声明:本文为博主原创文章,未经博主允许不得转载. 最近完成了www.leetcode.com的online judge中151道算法题目.除各个题目有特殊巧妙的解法以外,大部分题目都是经典的算法或者数据结构,因此做了如下小结,具体的解题思路可以搜索我的博客:LeetCode题解 题目 算法 数据结构 注意事项 Clone Graph BFS 哈希表 Word Ladder II

LeetCode All in One 题目讲解汇总(持续更新中...)

终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 如果各位看官们,大神们发现了任何错误,或是代码无法通过OJ,或是有更好的解法,或是有任何疑问,意见和建议的话,请一定要在对应的帖子下面评论区留言告知博主啊,多谢多谢,祝大家刷得愉快,刷得精彩,刷出美好未来- 博主制作了一款iOS的应用"Leetcode Meet Me",里面有Leetcode上所有的题目,并且贴上了博主的解法,随时随地都能

关于LRU缓存的实现算法讨论

业务模型 读.写.删的比例大致是7:3:1,至少要支持500w条缓存,平均每条缓存6k,要求设计一套性能比较好 的缓存算法. 算法分析 不考虑MemCached,Velocity等现成的key-value缓存方案,也不考虑脱离.NET gc自己管理内存,不考 虑随机读取数据及顺序读取数据的场景,目前想到的有如下几种LRU缓存方案 算法 分析 SortedDictionary .NET自带的,内部用二叉搜索树(应该不是普通树,至少是做过优化的树)实现的,检索为O (log n),比普通的Dicti