146. LRU 缓存机制
题目
方法思路
- 双向链表+
hashMap
hashMap
中保存key->node
的映射关系- 链表结点中需要保存
key
,value
和前后指针
- 需要定义虚拟头节点和尾结点,方便插入和删除
- 将当使用一个结点时,需要将该节点加入头部,需要删除时,删除尾部的结点并且删除
hashMap中的映射关系
,就实现了LRU的机制
代码
// 双链表结点定义
struct Node {
// 用来记录key,当删除双链表尾部时,可以通过key删除哈希表中对应的值
int key;
int value;
Node* next;
Node* pre;
Node(int _value) : value(_value) {};
};
class LRUCache {
private:
// cap记录初始的容量
int cap;
// size记录已经装入的键值对
int size;
// 哈希表,用来存储key->node的映射关系,用过哈希表的key直接定位双链表中的结点位置
unordered_map<int, Node*> hashmap;
// 双链表的头节点和尾结点
Node* head;
Node* tial;
public:
LRUCache(int capacity) {
// 初始cap和size
cap = capacity;
size = 0;
// 使用伪头节点和伪尾结点,并且初始情况两者相连
head = new Node(0);
tial = new Node(0);
head->next = tial;
head->pre = nullptr;
tial->pre = head;
tial->next = nullptr;
}
// 将temp结点移到头位置,表示最近使用
void moveToHead(Node* temp) {
// 将temp结点的前后结点相连,断开temp结点
temp->pre->next = temp->next;
temp->next->pre = temp->pre;
// 将temp结点插入头节点
insertToHead(temp);
}
int get(int key) {
// 如果在哈希表中找不到key值,返回-1,表示查找失败
if (hashmap.find(key) == hashmap.end()) return -1;
// 如果能找到,通过哈希表找到双链表的位置,并且返回value值
// 将该结点移到头部,表示最近使用过
Node* temp = hashmap[key];
int ans = temp->value;
moveToHead(temp);
return ans;
}
// 将temp结点插入头部
void insertToHead(Node* temp) {
temp->next = head->next;
temp->pre = head;
head->next->pre = temp;
head->next = temp;
}
// 删除尾部结点,也就是最久未使用的结点
void deleteTial() {
Node* temp = tial->pre;
temp->pre->next = tial;
tial->pre = temp->pre;
// 防止内存泄漏
delete temp;
}
void put(int key, int value) {
// 如果put的key->value在哈希表中存在,就修改对应结点中的value值
// 并且将该结点移动到头部,表示最近使用
if (hashmap.find(key) != hashmap.end()) {
Node* temp = hashmap[key];
temp->value = value;
moveToHead(temp);
return;
}
// 如果不存在,则生成新的结点,并插入双链表头部,将key->node加入到哈希表中
Node* temp = new Node(value);
temp->key = key;
insertToHead(temp);
hashmap[key] = temp;
// 更新size
size++;
// 当size超过cap值时,删除双链表中的尾结点,并且删除哈希表中对应的键值对,更新size
if (size > cap) {
Node* t = tial->pre;
hashmap.erase(t->key);
deleteTial();
size--;
}
}
};
/**
* 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);
*/
官方题解:146. LRU 缓存机制