链表:LRU缓存
LeetCode146 LRU缓存
class Node{
public:
int key;
int value;
Node* pre;
Node* next;
Node(int k=0,int v=0):key(k),value(v){}
};
class LRUCache {
private:
int capacity;
Node* dummy; //哨兵节点
unordered_map<int,Node*> key_node;
//删除一个节点(抽出一本书)
void remove(Node* x){
x->next->pre=x->pre;
x->pre->next=x->next;
}
//在链表头添加一个节点(把一本书放在最上面)
void push_front(Node* x){
x->pre=dummy;
x->next=dummy->next;
dummy->next=x;
x->next->pre=x;
}
//获取key对应的节点, 同时把节点移到链表头部
Node* get_node(int key){
auto it=key_node.find(key);
if(it==key_node.end()){//没有这个关键值(这本书)
return nullptr;
}
Node* node=it->second;
remove(node); //将这本书抽出来
push_front(node); //放在最上面
return node;
}
public:
LRUCache(int capacity):capacity(capacity),dummy(new Node()) {
dummy->next=dummy;
dummy->pre=dummy;
}
int get(int key) { //如果关键字key存在于缓存中,则返回关键字的值,否则返回-1
Node* node=get_node(key);
if(node==nullptr) return -1;
return node->value;
}
void put(int key, int value)
Node* node=get_node(key);
if(node!=nullptr){//关键字key已存在,变更其数据值value
node->value=value;
return;
}
else{ //如果不存在,则向缓存中插入该组 key-value。如果插入操作导致关键字数量超过 capacity ,则应该逐出最久未使用的关键字。
Node* new_node=new Node(key,value); //新书
key_node[key]=new_node;
push_front(new_node); //放在最上面
if(key_node.size()>capacity){ //书太多了
Node* back_node=dummy->pre; //找到最后一本书
key_node.erase(back_node->key);
remove(dummy->pre); //去掉最后一本书
delete back_node; //释放内存
}
}
}
};
/**
* 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(min(p, capacity)),p为put的调用次数