class Node {
constructor(key, value) {
this.key = key;
this.value = value;
this.frequency = 1;
this.prev = null;
this.next = null;
}
}
class LFUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
this.freqMap = new Map();
this.minFrequency = 1;
}
get(key) {
if (!this.cache.has(key)) {
return -1;
}
const node = this.cache.get(key);
this.updateFrequency(node);
return node.value;
}
put(key, value) {
if (this.capacity === 0) {
return;
}
if (this.cache.has(key)) {
const node = this.cache.get(key);
node.value = value;
this.updateFrequency(node);
} else {
if (this.cache.size >= this.capacity) {
this.evict();
}
const newNode = new Node(key, value);
this.cache.set(key, newNode);
this.addToFreqMap(newNode);
this.minFrequency = 1;
}
}
updateFrequency(node) {
const frequency = node.frequency;
this.freqMap.get(frequency).delete(node);
if (this.minFrequency === frequency && this.freqMap.get(frequency).size === 0) {
this.minFrequency += 1;
}
node.frequency += 1;
this.addToFreqMap(node);
}
addToFreqMap(node) {
const frequency = node.frequency;
if (!this.freqMap.has(frequency)) {
this.freqMap.set(frequency, new Set());
}
this.freqMap.get(frequency).add(node);
}
evict() {
const minFreqNodes = this.freqMap.get(this.minFrequency);
const evictNode = minFreqNodes.values().next().value;
minFreqNodes.delete(evictNode);
this.cache.delete(evictNode.key);
}
}
const lfuCache = new LFUCache(2);
lfuCache.put(1, 1);
lfuCache.put(2, 2);
console.log(lfuCache.get(1));
lfuCache.put(3, 3);
console.log(lfuCache.get(2));
console.log(lfuCache.get(3));
console.log(lfuCache.get(1));