Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
这题的关键是要选好数据结构,刚开始用链表保存key, 每当访问某个key时便将key移到链表首部,当容量满时移除链表的尾部元素。虽然链表的删除时间复杂度为O(1), 但是链表的查找时间却是O(L), 超时。
之后使用两个缓存表,并给每个key设一个id,每当访问一个key时,会将访问的key的id更新为当前的m_id,然后m_id自加1,其中一个缓存表tab1为:<key,<value,id>>, 另一个缓存表tab2为: <id,key>, 这样就可以根据给定的key获取key对应的value和id,然后再根据这个id来查找tab2中value为key项,删除该项,再插入(m_id,key), 插入时是根据id自动排好序的,因此每更新一个key项,该key项总会移到tab2的尾部, 这样容量满时,只需找到tab2的首部,移除掉就行了。
class LRUCache{
private:
int m_id; //key的id,id越大优先级越高,每当访问一个key,更新该key的id为m_id, 然后m_id++
int m_capacity;
map<int,pair<int,int> > m_tab1; //<key,<value,id> > >速查表,加个id是为了在m_tab2中找到id对应的关键字
map<int,int> m_tab2; //<id,key>,将关键字按id排序(LRU排序)
public:
LRUCache(int capacity) {
m_id = 0;
m_capacity = capacity;
}
int get(int key) {
if(m_tab1.find(key)!=m_tab1.end()){
//更新关键字key的id
pair<int,int> tmp = m_tab1[key];
int key_id = tmp.second; //key对应的id
m_tab2.erase(key_id); //移除旧的<id,key>
m_tab2[m_id] = key; //将key的id更新为m_id
m_tab1[key] = make_pair(tmp.first,m_id); //同时更新m_tab1中的<key,<value,id> >的id
m_id++;
return tmp.first;
}
else return -1;
}
void set(int key, int value) {
if(m_tab1.find(key)!=m_tab1.end()){
int key_id = m_tab1[key].second;
m_tab2.erase(key_id);
}
else if(m_tab1.size()==m_capacity){
m_tab1.erase((m_tab2.begin())->second); //移除掉id最小的key
m_tab2.erase(m_tab2.begin());
}
m_tab1[key] = make_pair(value,m_id);
m_tab2[m_id] = key;
m_id++;
}
};