存和取都需要O(1),原本可以用哈希表实现,但是题目还有个条件,在容量超过capacity的时候删掉最久不用的元素,因此增加一个双向链表,在数据被get和put的时候均将对应的元素移动到表尾。这样越靠近表尾越近被使用过,每次需要删除最久未使用的就删掉表头的元素即可。
struct DListNode {
int data;
int key;
DListNode* next=nullptr;
DListNode* pred = nullptr;
};
class LRUCache {
public:
unordered_map<int ,DListNode*> umap;
DListNode* head = nullptr;
DListNode* tail = nullptr;
int cap;
LRUCache(int capacity) {
cap = capacity;
head = new DListNode();
tail = new DListNode();// 设置头节点和尾节点
head -> next = tail;
tail -> pred = head;
}
int get(int key) {
if (umap.find(key) == umap.end()){
return -1;
}
else {
DListNode* current = umap[key];
// 访问了,元素挪到链表最后
current -> pred -> next = current -> next;
current -> next -> pred = current -> pred;
current -> next = tail;
current -> pred = tail -> pred;
tail -> pred -> next = current;
tail -> pred = current;
return current ->data;
}
}
void put(int key, int value) {
// 修改的元素和新加入的元素都加到链表最后。
if (umap.find(key) != umap.end()) {
umap[key] -> data = value;
DListNode* current = umap[key];
current -> pred -> next = current -> next;
current -> next -> pred = current -> pred;
current -> next = tail;
current -> pred = tail -> pred;
tail -> pred -> next = current;
tail -> pred = current;
}
else {
DListNode* new_node = new DListNode();
new_node -> data = value;
new_node -> key = key;
umap[key] = new_node;
new_node -> next = tail;
new_node -> pred = tail -> pred;
tail -> pred -> next = new_node;
tail -> pred = new_node;
if (umap.size() > cap) {
DListNode* deleteNode = head -> next;
head -> next = deleteNode -> next;
deleteNode -> next -> pred = head;
umap.erase(deleteNode->key);
delete deleteNode;
}
}
}
};
/**
* 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);
*/