LeetCode - LRU Cache

LRU Cache

2014.2.13 18:15

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:

  My LRU cache is made up of two parts, a hash table and a double-linked list.

  Hash table provides O(1) access to every element in the cache. Double-linked list allows you to move a node to the head or to the tail in O(1) time, although you'll need O(n) time locating this node. With their combiantion, both process can reach O(1) complexity.

  The double-linked list is handwritten, while the hash table is unordered_map from new STL.

  It's quite easy to make mistake on linked list, especially when it is double-linked.

  Whenever set() or get() is called, the node visitied or created should be put on the front of the list.

  Time complexity is O(1) for both set() and get(), linked list and hashing both use O(n) space.

Accepted code:

  1 // 1WA, 1AC, double-linked list + unordered_map

  2 #include <unordered_map>

  3 using  namespace std;

  4 

  5 typedef struct DoubleLinkedListNode{

  6 public:

  7     int key;

  8     int value;

  9     struct DoubleLinkedListNode *left;

 10     struct DoubleLinkedListNode *right;

 11     DoubleLinkedListNode(int _key = 0, int _value = 0): key(_key), value(_value), left(nullptr), right(nullptr) {}

 12 }DoubleLinkedListNode;

 13 

 14 class LRUCache{

 15 public:

 16     LRUCache(int capacity) {

 17         this->capacity = capacity;

 18         this->size = 0;

 19         this->head = this->tail = nullptr;

 20         this->hash_table.clear();

 21     }

 22     

 23     int get(int key) {

 24         if (size == 0) {

 25             // the LRU cache is empty.

 26             return KEY_NOT_FOUND;

 27         }

 28         

 29         unordered_map<int, DoubleLinkedListNode *>::iterator mit;

 30         

 31         mit = hash_table.find(key);

 32         if (mit != hash_table.end()) {

 33             // the key exists in the cache.

 34             DoubleLinkedListNode *ptr = mit->second;

 35             if (ptr == head) {

 36                 // do nothing

 37             } else if (ptr == tail) {

 38                 // ptr is the tail node.

 39                 tail = ptr->left;

 40                 tail->right = nullptr;

 41                 ptr->left = nullptr;

 42                 ptr->right = head;

 43                 head->left = ptr;

 44                 head = ptr;

 45             } else {

 46                 // ptr is at middle of the list.

 47                 DoubleLinkedListNode *ptr1, *ptr2;

 48                 ptr1 = ptr->left;

 49                 ptr2 = ptr->right;

 50                 ptr1->right = ptr2;

 51                 ptr2->left = ptr1;

 52                 ptr->left = nullptr;

 53                 ptr->right = head;

 54                 head->left = ptr;

 55                 head = ptr;

 56             }

 57             return ptr->value;

 58         } else {

 59             // key not found.

 60             return KEY_NOT_FOUND;

 61         }

 62     }

 63     

 64     void set(int key, int value) {

 65         if (capacity == 0) {

 66             // no room to place anything.

 67             return;

 68         }

 69         

 70         unordered_map<int, DoubleLinkedListNode *>::iterator mit;

 71         mit = hash_table.find(key);

 72         if (mit != hash_table.end()) {

 73             // the key exists in the cache.

 74             DoubleLinkedListNode *ptr = mit->second;

 75             if (ptr == head) {

 76                 // do nothing

 77             } else if (ptr == tail) {

 78                 // ptr is the tail node.

 79                 tail = ptr->left;

 80                 tail->right = nullptr;

 81                 ptr->left = nullptr;

 82                 ptr->right = head;

 83                 head->left = ptr;

 84                 head = ptr;

 85             } else {

 86                 // ptr is at middle of the list.

 87                 DoubleLinkedListNode *ptr1, *ptr2;

 88                 ptr1 = ptr->left;

 89                 ptr2 = ptr->right;

 90                 ptr1->right = ptr2;

 91                 ptr2->left = ptr1;

 92                 ptr->left = nullptr;

 93                 ptr->right = head;

 94                 head->left = ptr;

 95                 head = ptr;

 96             }

 97             ptr->value = value;

 98         } else {

 99             DoubleLinkedListNode *ptr = nullptr;

100             if (size < capacity) {

101                 // still some space left.

102                 // put the new item at front, not rear.

103                 ptr = new DoubleLinkedListNode(key, value);

104                 if (head != nullptr) {

105                     head->left = ptr;

106                     ptr->right = head;

107                 } else {

108                     tail = ptr;

109                 }

110                 head = ptr;

111                 hash_table[key] = ptr;

112                 ++size;

113             } else {

114                 // capacity is reached.

115                 ptr = tail;

116                 hash_table.erase(tail->key);

117                 ptr->key = key;

118                 ptr->value = value;

119                 if (head != tail) {

120                     tail = ptr->left;

121                     tail->right = nullptr;

122                     ptr->left = nullptr;

123                     ptr->right = head;

124                     head->left = ptr;

125                     head = ptr;

126                 }

127                 hash_table[key] = ptr;

128             }

129         }

130     }

131 private:

132     static const int KEY_NOT_FOUND = -1;

133     int capacity;

134     int size;

135     DoubleLinkedListNode *head;

136     DoubleLinkedListNode *tail;

137     unordered_map<int, DoubleLinkedListNode *> hash_table;

138 };

 

你可能感兴趣的:(LeetCode)