LRU Cache
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(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.
Follow up:
Could you do both operations in O(1) time complexity?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
思路:這題其實就是實現操作系統中的LRU置換算法。LRU算法的含義是當內存中頁面滿了(這題中就是容量滿了),置換頁面時,需要將原先存在的頁面置換出來,而置換出的頁面是最久沒有被訪問過的頁面。
這題我採用一個vector
(因爲需要刪除map中的key,value對,所以存儲的是key)模擬一個隊列,vector根據時間順序來排序,最近訪問過的頁面在vector的最後,而最久沒有訪問過的頁面在vector的第一個元素,每次put新的<key, value>
如果頁面(vector)滿了則需要將key == vecrtor[0]
的鍵值對刪除,同時在vector
的最後插入新加入的頁面(key),每次get操作後也要更新vector
。具體的細節見代碼和註釋。
C++ map+vector
class LRUCache {
public:
unordered_map<int, int> dic;
vector<int> time;//最近加入或者最近使用過的key放在最後
int c;
LRUCache(int capacity) {
c = capacity;
}
int get(int key) {
unordered_map<int, int>::iterator iter = dic.find(key);
if(iter == dic.end())
return -1;//not found
else{
vector<int>::iterator it = std::find(time.begin(), time.end(), key);
time.erase(it);//訪問過的元素放到末尾
time.push_back(key);
return iter->second;//value
}
}
void put(int key, int value) {
if(dic.count(key))//key 已經存在cache中
{
dic[key] = value;//key設爲新的value
vector<int>::iterator it = std::find(time.begin(), time.end(), key);
time.erase(it);//更新key的使用時間
time.push_back(key);
}
else{//key不在cache中
if(time.size()==c){//cache滿了,先刪除一個最近最久沒有使用的元素
int pop = time[0];
time.erase(time.begin());//刪除最久沒有使用的元素,放在time的開頭
dic.erase(pop);
}
time.push_back(key);
dic[key] = value;
}
}
};
/**
* 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);
*/
結果
速度比較慢,然後我想制約這個速度的應該是vector的刪除操作?因爲在連續存儲的順序表中刪除中間一個元素可能需要移動後面的元素?不知道vector是不是這樣實現的,然後我把vector換成list,竟然速度更慢了?有點迷,所以拖了幾天才寫博客,但是現在還不是很清楚,看了評論區,大部分人都是自己實現雙向鏈表來實現刪除才能達到很高的效率,先留個坑,以後填吧。。。