Leetcode難題,題目為:
運用你所掌握的資料結構,設計和實現一個 LRU (最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get
和 寫入資料 put
。
獲取資料 get(key)
- 如果金鑰 (key) 存在於快取中,則獲取金鑰的值(總是正數),否則返回 -1。
寫入資料 put(key, value)
- 如果金鑰不存在,則寫入其資料值。當快取容量達到上限時,它應該在寫入新資料之前刪除最近最少使用的資料值,從而為新的資料值留出空間。
進階:
你是否可以在 O(1) 時間複雜度內完成這兩種操作?
示例:
LRUCache cache = new LRUCache( 2 /* 快取容量 */ ); 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); // 返回 4
這一題是非常典型的應用STL的演算法題,同時還通過這個讓我們瞭解了一下系統內的LRU快取機制
這一題用的是unordered_map,list,pair這幾個STL常用的東西。如果不清楚的朋友可以查詢Cpp reference,下面題解給了註釋
題解以及註釋
1 class LRUCache { 2 public: 3 /*建構函式*/ 4 LRUCache(int capacity) : _capacity(capacity) {} 5 int get(int key) { 6 if (pos.find(key) != pos.end()) { 7 /*如果找到這個key所對應的值*/ 8 put(key, pos[key]->second); 9 return pos[key]->second; 10 } 11 return -1; 12 } 13 void put(int key, int value) { 14 if (pos.find(key) != pos.end()) 15 recent.erase(pos[key]); 16 else if (recent.size() >= _capacity) { 17 /*超出容量了,從pos和recent都刪除出現最早的那一個*/ 18 pos.erase(recent.back().first); 19 recent.pop_back(); 20 } 21 recent.push_front({ key, value }); 22 pos[key] = recent.begin(); 23 } 24 private: 25 int _capacity; 26 list<pair<int, int>> recent; 27 /*最近使用過的記錄,pair<int,int>表示鍵值對,用list模擬佇列*/ 28 unordered_map<int, list<pair<int, int>>::iterator> pos; 29 /**************** 30 value儲存的是一個迭代器,這是一個從key對映到位置的hash表, 31 這裡沒有再用value的原因是可以直接通過迭代器的位置找到value 32 ***************/ 33 };