146. Mécanisme de mise en cache LRU

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 LRUCachecatégories:

  • LRUCache(int capacity)En tant que capacitycache d'initialisation d' entier positif LRU

  • int get(int key)Si le mot-clé keyexiste 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^4temps getetput


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 fin
  • get(key), Si keyprésent, qui est inséré dans une queue
  • Lorsque vous supprimez, le nœud d'en-tête peut être supprimé et supprimé des keyenregistrements 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%
*/

Je suppose que tu aimes

Origine blog.csdn.net/MIC10086/article/details/114179476
conseillé
Classement