Lintcode 134. LRU缓冲策略
题目描述:为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据和写入数据。
- get(key) 获取数据:如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1。
- set(key, value) 写入数据:如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。
最终, 你需要返回每次 get 的数据。
代码使用哈希表+单向链表实现。
解题思路: 涉及删除和移动操作,使用链表,链表是有序的,一直维护,近期最多使用的放于尾部,那么每次缓存达到上限的时候,删除头部即可,其余为链表的基础操作模拟即可。
class KeyValue {
public:
int key, value;
KeyValue *next;
KeyValue(int key, int value) {
this->next = nullptr;
this->key = key;
this->value = value;
}
KeyValue() {
this->next = nullptr;
this->key = 0;
this->value = 0;
}
};
class LRUCache {
private:
unordered_map<int, KeyValue*> hash;
KeyValue *head;
KeyValue *tail;
int capacity, size;
void moveToTail(KeyValue *prev) {//将节点移动至尾部
if (tail == prev->next) {
return;
}
KeyValue *node = prev->next;//要移动的点的位置
prev->next = node->next;//记住要移动节点的下一个节点位置
if (nullptr != node->next) {
hash[node->next->key] = prev;//将要移动节点的下一个节点的hash映射修改一下
}
tail->next = node;
node->next = nullptr;
hash[node->key] = tail;
tail = node;
}
public:
/*
* @param capacity: An integer
*/LRUCache(int capacity) {
this->head = new KeyValue(0, 0);
this->tail = head;
this->capacity = capacity;
this->size = 0;
hash.clear();
}
/*
* @param key: An integer
* @return: An integer
*/
int get(int key) {
if (hash.find(key) == hash.end()) {//没有找到key
return -1;
}
moveToTail(hash[key]);//cache中有key的话,将其移到最右面(最新)
return hash[key]->next->value;//hash[key]为tail,是一个dummy节点,dummy->next才指向要找的value
}
/*
* @param key: An integer
* @param value: An integer
* @return: nothing
*/
void set(int key, int value) {
if (hash.find(key) != hash.end()) {//cache中存在key
hash[key]->next->value = value;//注:hash->next指向要查找的值,因为我们在用单链表实现且又需知要查找值的前继节点,所以使用dummy节点的方式
moveToTail(hash[key]);//将key移动到最右面(最新)
} else {
KeyValue *node = new KeyValue(key, value);
tail->next = node;//放于尾部
hash[key] = tail;//hash里面存的是dummy节点
tail = node;//尾指针向前移一步
size++;
if (size > capacity) {//超出cache上限
hash.erase(head->next->key);//删除头部数据
head->next = head->next->next;//头指针向前移一步
if (nullptr != head->next) {
hash[head->next->key] = head;
}
size--;
}
}
}
};