146. Mécanisme de mise en cache LRU
Description du titre
Utilisez la structure de données que vous connaissez pour concevoir et implémenter un mécanisme de mise en cache LRU (le moins récemment utilisé) .
Réaliser des LRUCache
catégories:
-
LRUCache(int capacity)
En tant quecapacity
cache d'initialisation d' entier positif LRU -
int get(int key)
Si le mot-clékey
existe dans le cache, la valeur de la clé est renvoyée, sinon-1
.
void put(int key, int value)
Si le mot-clé existe déjà, modifiez sa valeur de données; si le mot-clé n'existe pas, insérez le groupe "valeur-mot-clé". Lorsque la capacité du cache atteint la limite supérieure, il doit supprimer la valeur de données inutilisée la plus ancienne avant d'écrire de nouvelles données pour faire de la place pour la nouvelle valeur de données.
Avancé : vous pouvez O(1)
effectuer les deux opérations dans la complexité du temps?
Exemple:
输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
rapide:
-
1 <= capacity <= 3000
-
0 <= key <= 3000
-
0 <= value <= 10^4
-
Appelez la plupart du
3 * 10^4
tempsget
etput
répondre:
Liste à double lien + hachage.
En supposant que la priorité de la liste doublement chaînée diminue de la queue à la tête, alors:
put(key, value)
Insérez le nœud à la finget(key)
, Sikey
présent, qui est inséré dans une queue- Lorsque vous supprimez, le nœud d'en-tête peut être supprimé et supprimé des
key
enregistrements de la table de hachage
Complexité temporelle: O (1) O (1)O ( 1 )
Complexité d'espace supplémentaire: O (capacité) O (capacité)O ( c a p a c i t y )
class LRUCache {
public:
LRUCache(int capacity) : max_size(capacity) {
}
int get(int key) {
auto iter = hash_map.find( key );
if ( iter != hash_map.end() ) {
lst.splice( lst.end(), lst, iter->second );
return iter->second->second;
} else return -1;
}
void put(int key, int value) {
auto iter = hash_map.find( key );
if ( iter != hash_map.end() ) {
lst.splice( lst.end(), lst, iter->second );
iter->second->second = value;
} else {
hash_map[key] = lst.insert( lst.end(), {
key, value} );
if ( lst.size() > max_size ) {
hash_map.erase( lst.front().first );
lst.pop_front();
}
}
}
private:
using key_value_pair = pair<int, int>;
using list_iterator = list<key_value_pair>::iterator;
size_t max_size;
list<key_value_pair> lst;
unordered_map<int, list_iterator> hash_map;
};
/*
时间:92ms,击败:95.82%
内存:39MB,击败:71.53%
*/
Publiez une version d'une liste à double lien manuscrite et ajoutez un nœud de tête virtuel et un nœud de queue pour une utilisation facile.
class DLinkedNode {
public:
DLinkedNode( int _key = 0, int _val = 0 ) : key(_key), val(_val), next(nullptr), prev(nullptr) {
}
private:
int key, val;
DLinkedNode *next, *prev;
friend class LRUCache;
};
class LRUCache {
public:
void _insert (int key, int value) {
DLinkedNode *node = new DLinkedNode( key, value );
node->next = tail;
node->prev = tail->prev;
tail->prev->next = node;
tail->prev = node;
hash[key] = node;
++size;
}
void _delete () {
auto node = head->next;
head->next = node->next;
node->next->prev = head;
hash.erase( node->key );
delete node;
--size;
}
void remove( DLinkedNode* node ) {
node->prev->next = node->next;
node->next->prev = node->prev;
node->next = tail;
node->prev = tail->prev;
node->prev->next = node;
tail->prev = node;
}
LRUCache(int capacity) : max_size(capacity), size(0) {
head = new DLinkedNode();
tail = new DLinkedNode();
head->next = tail;
tail->prev = head;
}
int get(int key) {
auto iter = hash.find( key );
if ( iter == hash.end() ) return -1;
else {
remove( iter->second );
return iter->second->val;
}
}
void put(int key, int value) {
auto iter = hash.find( key );
if ( iter == hash.end() ) {
_insert( key, value );
if ( size > max_size ) _delete();
} else {
iter->second->val = value;
remove( iter->second );
}
}
private:
DLinkedNode *head, *tail;
int max_size, size;
unordered_map<int, DLinkedNode*> hash;
};
/*
时间:88ms,击败:97.84%
内存:38.8MB,击败:94.56%
*/