LRU Cache
Easy C++ KotlinEnunciado do problema
Projetar e implementar uma estrutura de dados para o cache LRU (Least Recently Used). Deve suportar as seguintes operações: obter e colocar.
get (key) - Obtém o valor (sempre será positivo) da chave se a chave existir no cache, caso contrário, retornará -1. put (chave, valor) - Defina ou insira o valor se a chave ainda não estiver presente. Quando o cache atingiu sua capacidade, ele deve invalidar o item usado menos recentemente antes de inserir um novo item.
Solução
No Cache LRU, a chave recente menos utilizada é despejada da memória. Uma maneira de manter um controle do uso da chave é manter a chave em um das extremidades na estrutura selecionada para simular a memória. Toda vez que uma chave é usada (sendo as ações de get ou put) o valor será colocado no início e, antes da operação put, removerá a chave menos usada se o tamanho máximo do array já foi alcançado.
Uma solução é manter um vetor de chaves e, cada vez que as funções são chamadas, o vetor é reorganizada para corresponder à condição declarada. Isso torna a solução O(n*m) onde n é o número de operações e m o tamanho máximo do cache.
Se uma lista encadeada for usada com um mapa não ordenado, é possível fazer a solução O(1) para ambas as operações (obter e colocar). O mapa será usado para manter uma faixa de todas as chaves na minha lista e os ponteiros para os nós da lista dessas chaves. Toda vez que uma ação é chamada, nós rearranjamos apenas o nó que foi usado colocando-o na frente da lista, e essas operações são O(1) para uma lista.
class LRUCache {
private:
struct Node{
int key, val;
Node(int k, int v){
key = k, val = v;
}
};
unordered_map<int, std::list<Node>::iterator> mapping;
list<Node> lru;
int maxSize;
public:
LRUCache(int capacity) {
maxSize = capacity;
}
int get(int key) {
if(mapping.find(key)!=mapping.end()){
int val = mapping[key]->val;
lru.erase(mapping[key]);
addFront(key,val);
return val;
}
return -1;
}
int removeBack(){
auto it = lru.back();
int key = it.key;
lru.pop_back();
return key;
}
void addFront(int key, int val){
lru.push_front(Node(key,val));
mapping[key]=lru.begin();
}
void put(int key, int value) {
if(mapping.find(key)!=mapping.end()){
lru.erase(mapping[key]);
}else if(lru.size()>=maxSize){
mapping.erase(removeBack());
}
addFront(key,value);
}
};
question from LeetCode