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.
题意:完成一个LRU缓存类,存储<key,value>映射表,具体功能为,初始化读入一个缓存大小capacity,之后又set和get两种操作:
get(key):得到对应key的value,若key不存在,返回-1
set(key):将key的值设为value,若缓存数据超过规定大小capacity,舍弃更新时间最远的数据,加入新数据。
注意:set和get对key的操作都算作对key的更新
分析:用一个map存储数据映射表mp,之后的难点在于,需要一个数据结构,将所有key按照更新时间排序,能够在O(1)找到最久远的(队头的)key并删除,且能在O(1)找到任意一个key并放到队尾,并将置为最新,即把它放到队尾。考虑过用set或者链表,但都不能解决问题。后来想到一种用两个map记录的方法,如下:
1、将所有key按更新时间组成一个“链表”,表头为最旧key,表尾为最新的key
2、用map<int,int> next,pre; 分别记录“链表”中key的前驱和后继,用lastkey和newkey记录表头和表尾。
3、每次set和get,只要操作的key在数据表mp中,更新key在链表中的位置,将其放到表尾,并更新对应的next和pre值,将newkey置为当前的key
4、若set时达到capacity,删除lastkey,更新链表,并从数据表mp中删除
这样,插入,更改,删除的复杂度均为O(1)。
代码:
class LRUCache{
private:
map<int,int> mp;
int cap;
map<int,int> next,pre;
int lastkey,newkey;
void update(int key)
{
if(newkey<0)
{
newkey = lastkey = key;
return;
}
if(next.find(key)!=next.end())
{
int nxt = next[key];
if(pre.find(key)!=pre.end())
{
int pr = pre[key];
next[pr] = nxt;
pre[nxt] = pr;
}
else
{
lastkey = nxt;
pre.erase(nxt);
}
next.erase(key);
}
if(newkey!=key)
{
next[newkey] = key;
pre[key] = newkey;
newkey = key;
}
}
void del()
{
if(next.find(lastkey)!=next.end())
{
int nxt = next[lastkey];
next.erase(lastkey);
pre.erase(nxt);
lastkey = nxt;
}
else
{
lastkey = newkey = -1;
}
}
public:
LRUCache(int capacity) {
cap = capacity;
lastkey = newkey = -1;
}
int get(int key) {
if(mp.find(key)!=mp.end())
{
update(key);
return mp[key];
}
return -1;
}
void set(int key, int value) {
update(key);
if(mp.find(key)==mp.end() && mp.size()==cap)
{
if(lastkey>0)
mp.erase(lastkey);
del();
}
mp[key] = value;
}
};