運用你所掌握的數據結構,設計和實現一個 LRU (最近最少使用) 緩存機制。它應該支持如下操做: 獲取數據 get 和 寫入數據 put 。緩存
獲取數據 get(key) - 若是密鑰 (key) 存在於緩存中,則獲取密鑰的值(老是正數),不然返回 -1。
寫入數據 put(key, value) - 若是密鑰不存在,則寫入其數據值。當緩存容量達到上限時,它應該在寫入新數據以前刪除最近最少使用的數據值,從而爲新的數據值留出空間。數據結構
進階:ide
你是否能夠在 O(1) 時間複雜度內完成這兩種操做?設計
示例:ci
LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );get
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 該操做會使得密鑰 2 做廢
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 該操做會使得密鑰 1 做廢
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4hash
思路:it
只有鏈表才能夠實現插入和刪除操做在O(1)時間複雜度內完成,因此存儲內容要用鏈表實現class
實現O(1)時間複雜度內訪問能夠用unordered_map和vector,可是vector不是關聯式容器,沒法進行key和list關聯,因此用unordered_map容器
class LRUCache { private: int capacity; list<pair<int,int>> ls;//只有鏈表才能實現插入和刪除時間複雜度O(1)——實現存儲功能 unordered_map<int,list<pair<int,int>>::iterator> hash;//哈希表實現,實現查找時間時間複雜度O(1)——實現查找功能 //unordered_map中key爲key,value爲list的地址 public: LRUCache(int _capacity):capacity(_capacity){} int get(int key) { if(hash.find(key)==hash.end()) return -1; //訪問事後,要放到鏈表頭部 int val=hash[key]->second;//取出list中的val ls.erase(hash[key]);//刪除鏈表中的源節點 ls.push_front({key,val});//剛訪問過的要放到鏈表頭 hash[key]=ls.begin();//更新hash表 return val; } void put(int key, int value) { if(hash.find(key)!=hash.end())//在放入LRU前該值若存在,在hash和ls中刪除相應的記錄 { ls.erase(hash[key]); hash.erase(key); } else if(hash.size()>=capacity)//若容量已經到達上限,在hash和ls中刪除最近最久沒有訪問的記錄 { hash.erase(ls.back().first); ls.pop_back(); } ls.push_front({key,value}); hash[key]=ls.begin(); return ; } }; /** * 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); */