Leetcode刷题LFU缓存
Posted 外部存储设备
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode刷题LFU缓存相关的知识,希望对你有一定的参考价值。
题目:https://leetcode-cn.com/problems/lfu-cache/
思路:
O(1)的数据结构:hashmap
维持最近使用:OrderdDict(详见LRU缓存问题)
使用一个hashmap维系key到出现频率的映射关系
另一个hashmap维系频率到数据(key-value键值对)的关系
由于 当存在平局(即两个或更多个键具有相同使用频率)时,应该去除 最近 最少使用的键。因此key-value键值对应该用OrderdDict存储
import collections
class LFUCache:
# self.key_fre是key到出现频率的映射关系
# self.fre_data格式:
# {
# fre1:{
# key1:value1,
# ...
# }
# ...
# }
def __init__(self, capacity: int):
self.capacity = capacity
self.count = 0
self.key_fre = {}
# 同一频率下,去除最近最少使用的健,退化为LRU缓存问题
self.fre_data = {}
self.min_fre = 1
# 更新某一键值对的频率
def update_fre(self, key, value=None):
# 需要从self.fre_data中取值
fre = self.key_fre[key]
next_fre = fre + 1
# 从原频率字典删除
res = self.fre_data[fre].pop(key)
# 如果当前频率是最小频率,且字典为空,则更新最小频次记录
if fre == self.min_fre and not self.fre_data[fre]:
self.min_fre = next_fre
# 插入下一个频率字典
if next_fre not in self.fre_data:
self.fre_data[next_fre] = collections.OrderedDict()
self.fre_data[next_fre][key] = value if value is not None else res
# 修改原key与频率的对应关系
self.key_fre[key] = next_fre
return res
def get(self, key: int) -> int:
if key not in self.key_fre:
return -1
return self.update_fre(key)
def put(self, key: int, value: int) -> None:
# capacity还能是0
if self.capacity == 0:
return
# 如果是更新,则要变更key所处频率字典
if key in self.key_fre:
self.update_fre(key, value)
else:
if self.count >= self.capacity:
# 缓存已满,从最小频次字典中pop最少使用的
item = self.fre_data[self.min_fre].popitem(last=False)
# 删掉对应key与频率的映射关系
del self.key_fre[item[0]]
else:
self.count += 1
# 新加入,更新最小频率
self.min_fre = 1
self.key_fre[key] = 1
if 1 not in self.fre_data:
self.fre_data[1] = collections.OrderedDict()
self.fre_data[1][key] = value
以上是关于Leetcode刷题LFU缓存的主要内容,如果未能解决你的问题,请参考以下文章