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;
}
};