Frequency buckets
Time O(1) per operation Space O(capacity)vals, freqs, buckets(freq → LinkedHashSet), minFreq. touch(key) moves a key to freq + 1. Evict the first key of buckets[minFreq].
capacity 2: put(1,1), put(2,2), get(1), put(3,3), get(2), get(3)vals(map)
freqs(map)
buckets (oldest first)(map)
state(vars)
Step 1/5put(1,1) and put(2,2): both keys are new, so each gets count 1 and joins bucket 1 in arrival order.
import java.util.*;
class LFUCache {
private final int capacity;
private final Map<Integer, Integer> vals = new HashMap<>(), freqs = new HashMap<>();
private final Map<Integer, LinkedHashSet<Integer>> buckets = new HashMap<>();
private int minFreq = 0;
public LFUCache(int capacity) { this.capacity = capacity; }
public int get(int key) {
if (!vals.containsKey(key)) return -1;
touch(key);
return vals.get(key);
}
public void put(int key, int value) {
if (capacity == 0) return;
if (vals.containsKey(key)) { vals.put(key, value); touch(key); return; }
if (vals.size() == capacity) {
int evict = buckets.get(minFreq).iterator().next();
buckets.get(minFreq).remove(evict);
vals.remove(evict);
freqs.remove(evict);
}
vals.put(key, value);
freqs.put(key, 1);
buckets.computeIfAbsent(1, k -> new LinkedHashSet<>()).add(key);
minFreq = 1;
}
private void touch(int key) {
int f = freqs.get(key);
buckets.get(f).remove(key);
if (f == minFreq && buckets.get(f).isEmpty()) minFreq++;
freqs.put(key, f + 1);
buckets.computeIfAbsent(f + 1, k -> new LinkedHashSet<>()).add(key);
}
}Verdict: LinkedHashSet gives O(1) insert, delete and oldest.