[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 th

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;
};
目录
相关文章
|
4月前
|
缓存 算法 索引
LeetCode146:LRU缓存
LeetCode146:LRU缓存
28 1
|
5月前
|
缓存
leetcode-146:LRU 缓存
leetcode-146:LRU 缓存
25 0
|
5月前
|
存储 缓存 算法
☆打卡算法☆LeetCode 146. LRU 缓存 算法解析
☆打卡算法☆LeetCode 146. LRU 缓存 算法解析
|
存储 缓存
图解LeetCode——146. LRU 缓存
图解LeetCode——146. LRU 缓存
103 1
|
缓存
leetcode 146 LRU缓存
leetcode 146 LRU缓存
103 0
leetcode 146 LRU缓存
|
缓存 算法
LeetCode 146. LRU Cache
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
87 0
LeetCode 146. LRU Cache
|
存储 缓存 算法
LeetCode146 手撕LRU算法的2种实现方法
LeetCode146 手撕LRU算法的2种实现方法
239 0
LeetCode146 手撕LRU算法的2种实现方法
|
存储 缓存 算法
「LeetCode」146-LRU缓存⚡️
「LeetCode」146-LRU缓存⚡️
121 0
「LeetCode」146-LRU缓存⚡️
|
缓存 Java C++
【LeetCode146】LRU缓存机制(list+unordered_map)
首先读懂题意: 首先缓存最大容量初始化为capacity这么大,然后实现: put(key,val)存入键值对;get(key)获得键key对应的值val,如果键key不存在则返回-1。
251 0
|
存储 缓存 API
LeetCode——LRU 缓存机制(借助Map)
LeetCode——LRU 缓存机制(借助Map)
93 0
LeetCode——LRU 缓存机制(借助Map)