8 min

LRU Cache

Cache com política Least Recently Used - remove o item menos recentemente usado quando cheio. Operações get e put em O(1).

DifícilO(1) / O(capacity)CacheHash TableLinked ListDesign

Visualizador Interativo

LRU CacheCapacidade: 3Passo 1 / 19
HEAD
mais recente
Cache vazio
TAIL
menos recente
Recente
Medio
Antigo (LRU)
Operando
Hash Table (key → node)
Vazio
Velocidade:800ms
Historico de Passos
#0Inicializando LRU Cache com capacidade 3

Como Funciona

LRU Cache é uma estrutura que combina duas ideias: Hash Table: para acesso O(1) por chave Doubly Linked List: para manter ordem de uso e remoção O(1) A lista mantém items ordenados por uso recente: mais recente na frente, menos recente no final. O hash mapeia chaves diretamente para nós da lista. Operações: - get(key): busca no hash, se existe move para frente e retorna valor - put(key, value): se existe atualiza e move para frente; senão cria nó, adiciona na frente, e se exceder capacidade remove o último (LRU) O truque dos nós sentinela (dummy head e tail) elimina casos especiais de lista vazia ou um elemento, simplificando muito o código.

A combinação de hash table + doubly linked list permite tanto acesso por chave quanto manutenção de ordem em O(1). Nenhuma estrutura sozinha consegue isso.

Passo a Passo

  1. Hash table mapeia key para nó da lista
  2. Lista duplamente encadeada mantém ordem de uso
  3. Get move o nó acessado para o início
  4. Put adiciona no início e remove do final se necessário
  5. Sentinelas head/tail simplificam inserção/remoção

Análise de Complexidade

⏱️Tempo
O(1)

Todas operações são O(1) - hash lookup e manipulação de ponteiros.

Ver prova

Hash table dá acesso O(1) ao nó, lista duplamente encadeada permite remoção e inserção O(1).

💾Espaco
O(capacity)

Armazena no máximo capacity items no hash e na lista.

🎯Melhor Caso
O(1)

Sempre O(1) independente do estado do cache.

⚠️Pior Caso
O(1)

Mesmo com eviction, operações são O(1).

Comparação com Outros Algoritmos

AlgoritmoTempoEspacoMelhor Para
LRU Cache(atual)O(1) get/putO(capacity)Cache de acesso frequente, memória limitada
LFU CacheO(1) get/putO(capacity)Quando frequência importa mais que recência
FIFO CacheO(1) get/putO(capacity)Simplicidade, ordem de chegada

Dicas e Erros Comuns

  • Usar lista simples (remoção do meio seria O(n))
  • Esquecer de atualizar o hash ao remover do cache
  • Não mover para frente no get (só conta como "usado" se mover)
  • Esquecer de tratar atualização de valor existente

Perguntas de Entrevista

Pratique respondendo a perguntas comuns de entrevistas tecnicas. Clique em uma pergunta para iniciar uma sessao de pratica com IA.

Implementacao

python
1class Node:Nó da Lista
2 def __init__(self, key=0, val=0):Nó da Lista
3 self.key = keyNó da Lista
4 self.val = valNó da Lista
5 self.prev = NoneNó da Lista
6 self.next = NoneNó da Lista
7
8
9class LRUCache:Estrutura do Cache
10 def __init__(self, capacity):Inicialização
11 self.cap = capacityInicialização
12 self.cache = {} # key -> nodeBusca no Hash
13 # Sentinelas para simplificar operacoes
14 self.head = Node()Inicialização
15 self.tail = Node()Inicialização
16 self.head.next = self.tailInicialização
17 self.tail.prev = self.headInicialização
18
19 def _remove(self, node):Remover Nó
20 node.prev.next = node.nextRemover Nó
21 node.next.prev = node.prevRemover Nó
22
23 def _add_front(self, node):Adicionar na Frente
24 node.next = self.head.nextAdicionar na Frente
25 node.prev = self.headAdicionar na Frente
26 self.head.next.prev = nodeAdicionar na Frente
27 self.head.next = nodeAdicionar na Frente
28
29 def get(self, key):Operação Get
30 if key not in self.cache:Busca no Hash
31 return -1Operação Get
32 node = self.cache[key]Busca no Hash
33 self._remove(node)Mover para Frente
34 self._add_front(node)Mover para Frente
35 return node.valOperação Get
36
37 def put(self, key, value):Operação Put
38 if key in self.cache:Busca no Hash
39 self._remove(self.cache[key])Remover Nó
40 node = Node(key, value)Nó da Lista
41 self.cache[key] = nodeBusca no Hash
42 self._add_front(node)Adicionar na Frente
43 if len(self.cache) > self.cap:Remover LRU
44 lru = self.tail.prevRemover LRU
45 self._remove(lru)Remover LRU
46 del self.cache[lru.key]Remover LRU
47