class LFUCache {
// key 到 value 的映射
HashMap<Integer, Integer> keyToValue;
// key 到 frequency 的映射
HashMap<Integer, Integer> keyToFrequency;
// frequency 到 key 列表的映射
HashMap<Integer, LinkedHashSet<Integer>> frequencyToKeys;
// 记录最小的频次
int minFrequency;
// 记录 LFU 缓存的最大容量
int capaciity;
public LFUCache(int capacity) {
keyToValue = new HashMap<>();
keyToFrequency = new HashMap<>();
frequencyToKeys = new HashMap<>();
this.capaciity = capacity;
this.minFrequency = 0;
}
public int get(int key) {
if (!keyToValue.containsKey(key)) {
return -1;
}
// key 对应的 Frequency 加一
increaseFrequency(key);
return keyToValue.get(key);
}
public void put(int key, int value) {
if (this.capaciity <= 0) return;
// key 已存在,修改对应的 val
if (keyToValue.containsKey(key)) {
keyToValue.put(key, value);
// key 对应的 Frequency 加一
increaseFrequency(key);
return;
}
// key 不存在,进行插入
// 容量不足时淘汰一个 Frequency 最小的 key
if (this.capaciity <= keyToValue.size()) {
removeMinFrequencyKey();
}
// 插入 key 和 value
keyToValue.put(key, value);
// 插入 的 key 对应的 Frequency 为 1
keyToFrequency.put(key, 1);
// 将 key 插入 Frequency 为 1 对应的 key 列表中
frequencyToKeys.putIfAbsent(1, new LinkedHashSet<>());
frequencyToKeys.get(1).add(key);
// 插入新的 key 后最小的 frequency 为 1
this.minFrequency = 1;
}
private void removeMinFrequencyKey() {
// 最小的 freqquency 对应的 key 列表
LinkedHashSet<Integer> keyList = frequencyToKeys.get(this.minFrequency);
// 淘汰的 key 为最久未使用的,即最先被插入的
int oldestKey = keyList.iterator().next();
// 更新 key 列表
keyList.remove(oldestKey);
// 更新 frequency 到 key 列表的映射
if (keyList.isEmpty()) {
frequencyToKeys.remove(this.minFrequency);
}
// 更新 key 到 value 的映射
keyToValue.remove(oldestKey);
// 更新 key 到 frequency 的映射
keyToFrequency.remove(oldestKey);
}
private void increaseFrequency(int key) {
int frequency = keyToFrequency.get(key);
// 更新 key 到 frequency 的映射
keyToFrequency.put(key, frequency + 1);
// 更新 frequency 到 key 列表的映射
// 将 key 从 frequency 对应的列表中删除
frequencyToKeys.get(frequency).remove(key);
// 将 key 加入 frequency + 1 对应的列表中
frequencyToKeys.putIfAbsent(frequency + 1, new LinkedHashSet<>());
frequencyToKeys.get(frequency + 1).add(key);
// frequency 对应的 key 列表空了,移除该 frequency
if (frequencyToKeys.get(frequency).isEmpty()) {
frequencyToKeys.remove(frequency);
// 如果该 frequency 恰好是 minFrequency,更新 minFrequency 的值
if (frequency == this.minFrequency) {
this.minFrequency++;
}
}
}
}
/**
* Your LFUCache object will be instantiated and called as such:
* LFUCache obj = new LFUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
leetcode-460-LFU缓存
最新推荐文章于 2022-09-07 17:53:33 发布