146. Mecanismo de almacenamiento en caché de LRU

146. Mecanismo de almacenamiento en caché de LRU

Descripción del Título

Utilice la estructura de datos que conoce para diseñar e implementar un mecanismo de almacenamiento en caché LRU (menos utilizado recientemente) .

Darse cuenta de las LRUCachecategorías:

  • LRUCache(int capacity)En capacidad como capacityLRU de caché de inicialización de enteros positivos

  • int get(int key)Si la palabra clave keyexiste en la caché, se devuelve el valor de la clave, de lo contrario -1.

  • void put(int key, int value)Si la palabra clave ya existe, cambie su valor de datos; si la palabra clave no existe, inserte el grupo de "valor-palabra clave". Cuando la capacidad de la caché alcanza el límite superior, debe eliminar el valor de datos no utilizado más antiguo antes de escribir nuevos datos para dejar espacio para el nuevo valor de datos.

Avanzado : ¿puede O(1)completar ambas operaciones dentro de la complejidad del tiempo?

Ejemplo:

输入
["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

inmediato:

  • 1 <= capacity <= 3000

  • 0 <= key <= 3000

  • 0 <= value <= 10^4

  • Llame la mayoría de las 3 * 10^4veces getyput


responder:

Lista de doble enlace + hash.

Suponiendo que la prioridad de la lista doblemente enlazada disminuye de la cola a la cabeza, entonces:

  • put(key, value) Inserte el nodo al final
  • get(key), Si está keypresente, que se inserta en una cola
  • Cuando elimina, el nodo de encabezado se puede eliminar y eliminar de los keyregistros de la tabla hash

Complejidad de tiempo: O (1) O (1)O ( 1 )

Complejidad de espacio adicional: O (capacidad) O (capacidad)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%
*/

Publique una versión de una lista de doble enlace escrita a mano y agregue un nodo principal virtual y un nodo final para facilitar la operación.

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%
*/

Supongo que te gusta

Origin blog.csdn.net/MIC10086/article/details/114179476
Recomendado
Clasificación