1. 手写LRU缓存淘汰算法
思路:使用链表和unordered_map来组织数据,其中链表结点为一个结构体,包含key和value,而unordered_map的结点为int到链表结点迭代器的映射,通过unordered_map来实现快速索引,通过链表来实现快速删除和更新,以完成LRU功能。
越靠近链表尾部表示越近的数据
struct Node {
int key;
int value;
Node(int k, int v) : key(k), value(v) {}
};
class LRUCache {
private:
int _capacity;
list<Node> lst;
unordered_map<int, list<Node>::iterator> mp;
void update(list<Node>::iterator iter, int key) {
lst.push_back(*iter);
lst.erase(iter);
mp[key] = (--lst.end());
}
public:
LRUCache(int capacity) : _capacity(capacity) {}
int get(int key) {
// 1.若不存在返回-1
if (0 == mp.count(key)) {
return -1;
}
// 2.若存在返回对应数据值,同时更新mp和lst
else {
// 查找
auto iter = mp[key];
// 更新链表和映射表
update(iter, key);
return lst.back().value;
}
}
void put(int key, int value) {
// 1.关键值已经存在
if (0 != mp.count(key)) {
(*mp[key]).value = value;
// 更新链表和映射表
update(mp[key], key);
}
else {
// 2.1 容量达到上限
if (_capacity == lst.size()) {
mp.erase(lst.front().key);
lst.pop_front();
}
// 2.2 容量未达到上限
lst.push_back(Node(key,value));
mp[key] = (--lst.end());
}
}
};
/**
* 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);
*/
时间复杂度O(1),空间复杂度O(n)
2. 使用pair<int, int>代替Node
class LRUCache {
private:
int _capacity;
list<pair<int, int>> lst;
unordered_map<int, list<pair<int, int>>::iterator> mp;
void update(list<pair<int, int>>::iterator iter, int key) {
lst.push_back(*iter);
lst.erase(iter);
mp[key] = (--lst.end());
}
public:
LRUCache(int capacity) : _capacity(capacity) {}
int get(int key) {
// 1.若不存在返回-1
if (0 == mp.count(key)) {
return -1;
}
// 2.若存在返回对应数据值,同时更新mp和lst
else {
// 查找
auto iter = mp[key];
// 更新链表和映射表
update(iter, key);
return lst.back().second;
}
}
void put(int key, int value) {
// 1.关键值已经存在
if (0 != mp.count(key)) {
(*mp[key]).second = value;
// 更新链表和映射表
update(mp[key], key);
}
else {
// 2.1 容量达到上限
if (_capacity == lst.size()) {
mp.erase(lst.front().first);
lst.pop_front();
}
// 2.2 容量未达到上限
lst.push_back({key,value});
mp[key] = (--lst.end());
}
}
};
/**
* 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);
*/