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.
Solution From 水印人生:
class LRUCache { class ListNode { public: ListNode(int v, int k) : val(v), key(k) { prev = NULL; next = NULL; } int val; int key; ListNode *next; ListNode *prev; }; public: int c; ListNode *head; ListNode *tail; map<int, ListNode *> key_node_map; LRUCache(int capacity) : c(capacity) { head = NULL; tail = NULL; } int get(int key) { if (key_node_map.find(key) == key_node_map.end()) return -1; else { int temp = key_node_map[key]->val; set(key, temp); return temp; } } void set(int key, int value) { if (key_node_map.find(key) == key_node_map.end()) { ListNode *n = new ListNode(value, key); key_node_map[key] = n; n->next = head; n->prev = NULL; if (head!=NULL) head->prev = n; if (!tail) tail = n; head = n; if (key_node_map.size() > c) { key_node_map.erase(tail->key); ListNode *temp = tail->prev; delete tail; if (temp) { temp->next = NULL; tail = temp; } else { tail = NULL; } } } else { ListNode *n = key_node_map[key]; n->val = value; if (n->prev != NULL) n->prev->next = n->next; if (n->next != NULL) n->next->prev = n->prev ? n->prev : n; if (n->next == NULL) tail = n->prev ? n->prev : n; if (n->prev != NULL) { n->next = head; head->prev = n; n->prev = NULL; head = n; } } } };
Solution from 水中鱼:
1 class LRUCache{ 2 public: 3 struct CacheEntry 4 { 5 public: 6 int key; 7 int value; 8 CacheEntry(int k, int v) :key(k), value(v) {} 9 }; 10 11 LRUCache(int capacity) { 12 m_capacity = capacity; 13 } 14 15 int get(int key) { 16 if (m_map.find(key) == m_map.end()) 17 return -1; 18 19 MoveToHead(key); 20 return m_map[key]->value; 21 } 22 23 void set(int key, int value) { 24 if (m_map.find(key) == m_map.end()) 25 { 26 CacheEntry newItem(key, value); 27 if (m_LRU_cache.size() >= m_capacity) 28 { 29 //remove from tail 30 m_map.erase(m_LRU_cache.back().key); 31 m_LRU_cache.pop_back(); 32 } 33 34 // insert in head. 35 m_LRU_cache.push_front(newItem); 36 m_map[key] = m_LRU_cache.begin(); 37 return; 38 } 39 40 m_map[key]->value = value; 41 MoveToHead(key); 42 } 43 44 private: 45 unordered_map<int, list<CacheEntry>::iterator> m_map; 46 list<CacheEntry> m_LRU_cache; 47 int m_capacity; 48 49 void MoveToHead(int key) 50 { 51 //Move key from current location to head 52 auto updateEntry = *m_map[key]; 53 m_LRU_cache.erase(m_map[key]); 54 m_LRU_cache.push_front(updateEntry); 55 m_map[key] = m_LRU_cache.begin(); 56 } 57 58 };