[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;
};
目录
相关文章
|
8月前
|
缓存 NoSQL Go
【LeetCode 热题100】146:LRU 缓存(详细解析)(Go语言版)
本文详细解析了力扣 146 题——LRU 缓存机制的实现方法。通过结合哈希表与双向链表,确保 `get` 和 `put` 操作均在 O(1) 时间内完成。哈希表用于快速查找,双向链表记录访问顺序,支持最近使用数据的高效更新与淘汰。代码以 Go 语言实现,结构清晰,涵盖核心操作如节点移动、插入与删除。此题为面试高频考点,适用于数据缓存、页面置换等场景,掌握后可加深对缓存策略的理解。
416 4
|
缓存 算法 索引
LeetCode146:LRU缓存
LeetCode146:LRU缓存
140 1
|
缓存
leetcode-146:LRU 缓存
leetcode-146:LRU 缓存
95 0
|
存储 缓存 算法
☆打卡算法☆LeetCode 146. LRU 缓存 算法解析
☆打卡算法☆LeetCode 146. LRU 缓存 算法解析
|
存储 缓存
图解LeetCode——146. LRU 缓存
图解LeetCode——146. LRU 缓存
241 1
|
缓存
leetcode 146 LRU缓存
leetcode 146 LRU缓存
160 0
leetcode 146 LRU缓存
|
缓存 算法
LeetCode 146. LRU Cache
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
131 0
LeetCode 146. LRU Cache
|
存储 缓存 算法
LeetCode146 手撕LRU算法的2种实现方法
LeetCode146 手撕LRU算法的2种实现方法
497 0
LeetCode146 手撕LRU算法的2种实现方法
|
存储 缓存 算法
「LeetCode」146-LRU缓存⚡️
「LeetCode」146-LRU缓存⚡️
225 0
「LeetCode」146-LRU缓存⚡️
|
存储 缓存 API
LeetCode——LRU 缓存机制(借助Map)
LeetCode——LRU 缓存机制(借助Map)
140 0
LeetCode——LRU 缓存机制(借助Map)

热门文章

最新文章