Leetcode 146. LRU缓存机制
题目
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果关键字 (key) 存在于缓存中,则获取关键字的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字/值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
测试样例
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得关键字 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得关键字 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
题解
双向链表+哈希表
通过哈希表记录key对应的节点,当get时,查找节点并把它放到链表头;当put时,把它放到链表头,如果容量大于设定容量,则把链表尾舍弃一个节点。详细过程见代码
代码
struct Node{ //双向链表
int key;
int val;
Node *pre;
Node *next;
Node(int key,int val){
this->key = key;
this->val = val;
pre = NULL;
next = NULL;
}
};
Node* head;
Node* tail;
int capacity,have;
unordered_map<int,Node*> list;
LRUCache(int capacity) {
have = 0;
head = NULL;
tail = NULL;
this->capacity = capacity;
}
int get(int key) {
if(list.find(key) != list.end()){ //存在key
Node* node = list[key];
if(node != head){ //该节点不是头节点,则把它放到头节点
node->pre->next = node->next;
if(node == tail){ //如果是尾节点,则更新尾节点
tail = node->pre;
}else{
node->next->pre = node->pre;
}
node->next = head;
node->pre = NULL;
head->pre = node;
head = node;
}
return list[key]->val;
}else{
return -1;
}
}
void put(int key, int value) {
if(list.find(key) == list.end()){ //如果key不在缓存中
Node* newNode = new Node(key,value);
newNode->next = head;
if(head != NULL)
head->pre = newNode;
else tail = newNode;
head = newNode;
have++;
list[key] = head;
if(have > capacity){ //容量大于设定容量,舍弃尾节点,并更新尾节点
list.erase(tail->key);
tail = tail->pre;
tail->next = NULL;
have--;
}
}else{ //在缓存中
Node* node = list[key];
if(node != head){ //将该节点放到头节点
node->pre->next = node->next;
if(node == tail){
tail = node->pre;
}else{
node->next->pre = node->pre;
}
node->next = head;
node->pre = NULL;
head->pre = node;
head = node;
}
node->val = value; //更新value
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lru-cache
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。