Leetcode 146. LRU 缓存 哈希表 + 双向链表
原题链接:Leetcode 146. LRU 缓存
LRU(Least Recently Used,最近最少使用)缓存是一种内存数据管理策略,核心思想是:当缓存空间满时,优先淘汰 “最近一段时间内最少被访问” 的数据,为新数据腾出空间。它的设计目标是利用 “局部性原理”(程序或用户访问数据时,往往会在短时间内重复访问同一批数据),尽可能保留高频访问的数据,从而减少对底层存储(如数据库、硬盘)的依赖,提升数据读取效率。
LRU 的行为围绕 “访问” 和 “淘汰” 两个关键场景展开:
- 数据访问时(读 / 写):
- 若数据已在缓存中(“命中”),则将其标记为 “最近使用过”(更新它的访问优先级,避免被优先淘汰);
- 若数据不在缓存中(“未命中”),则将其存入缓存;若缓存已满,先淘汰 “最久未访问” 的数据,再存入新数据。
- 缓存满时淘汰:
严格选择 “最近一段时间内没有被访问过” 或 “访问频率最低” 的数据进行删除。
LRU 的高效实现需要满足两个核心需求:
- 快速查找数据(判断是否在缓存中)
- 快速更新 / 删除数据(调整访问优先级、淘汰旧数据)
- 经典实现采用 “哈希表 + 双向链表” 的组合
代码参考官解:LRU缓存机制
// 设计一个双向链表结构体
struct Node{int key,value;Node* prev;Node* next;Node():key(0),value(0),prev(nullptr),next(nullptr) {};Node(int k,int v):key(k),value(v),prev(nullptr),next(nullptr) {};
};class LRUCache {
private:int size;int capacity;Node* head;Node* tail;unordered_map<int,Node*> cache;
public:LRUCache(int _capacity): capacity(_capacity),size(0) {head = new Node();tail = new Node();head->next = tail;tail->prev = head;}int get(int key) {// 如果在当前缓存内没有找到if(!cache.count(key)){return -1;}// 如果找到Node* node = cache[key];move_to_head(node);return node->value;}void put(int key, int value) {// 如果在当前缓存内没有找到if(!cache.count(key)){// 如果 key 不存在,创建一个新的节点Node* node = new Node(key,value);// 添加进哈希表cache[key]=node;size++;// 添加至双向链表的头部add_to_head(node);if(size>capacity){// 如果超出容量,删除双向链表的尾部节点Node* drop_node = remove_tail();// 删除哈希表中对应的项cache.erase(drop_node->key);// 防止内存泄漏delete drop_node;size--;}}//如果当前缓存中有else{// 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部Node* node = cache[key];node->value = value;move_to_head(node);}}void add_to_head(Node* node){node->prev = head;node->next = head->next;head->next->prev = node;head->next = node;}void remove_node(Node* node){node->prev->next = node->next;node->next->prev = node->prev;}void move_to_head(Node* node){remove_node(node);add_to_head(node);}Node* remove_tail(){Node* node = tail->prev;remove_node(node);return node;}};/*** Your LRUCache object will be instantiated and called as such:* LRUCache* obj = new LRUCache(capacity);* int param_1 = obj->get(key);* obj->put(key,value);*/