力扣hot100:146. LRU 缓存

听说华为实习笔试考了这题
如何使得插入操作时 O ( 1 ) O(1) O(1)呢?我们需要维护一个时间的长短,以便于取出离现在最长的时间,这个时间比较容易实现,我们维护一个time表示当前时间,从0开始,然后在使用的一些关键字里面,当一个关键字使用的时间越小,那么它越久未被使用,我们只需要维护一个关键字使用的最小值就行,并且还需要有更新操作。
由于结点和值都是通过key来查询的,而查询只需要判断key,因此我们可以只使用一个哈希表,来同时维护这两个信息。

class LRUCache {
public:
LRUCache(int capacity) {
this->capacity = capacity;
dummy = new List;
end = dummy;
}
int get(int key) {
if(mp.count(key) == 1){
put_to_end(key);
return mp[key].first;
}
return -1;
}
void put(int key, int value) {
if(mp.count(key) == 1){
mp[key].first = value;
put_to_end(key);
return;
}
//判断是否超出容量
if(size == capacity){
List * temp = dummy->next;
dummy->next = temp->next;
if(temp->next) temp->next->pre = dummy;
mp.erase(temp->key);
if(temp == end) end = temp->pre;
delete temp;
}else ++size;
//插入全新元素
List * lst = new List;
lst->key = key;
mp[key] = {value,lst};
//放到末尾
lst->pre = end;
end->next = lst;
end = lst;
return;
}
private:
struct List{
List * pre = nullptr;
List * next = nullptr;
int key;//该key用于删除头结点
};
void put_to_end(int key){
List * access = mp[key].second;
if(access == end) return;
access->pre->next = access->next;
if(access->next) access->next->pre = access->pre;
access->next = nullptr;
access->pre = end;
end->next = access;
end = access;
return;
}
private:
unordered_map<int,pair<int,List *>> mp;
int capacity;
int size = 0;
List * dummy;
List * end;
};
需要注意的点:
写完之后可以再思考一个,LRU:
既然这是一个面试常考的题,那么写完后可以记住:LRU 缓存机制可以通过哈希表辅以双向链表实现,我们用一个哈希表和一个双向链表维护所有在缓存中的键值对。
