- LFU缓存 设计并实现最不经常使用(LFU)缓存的数据结构。它应该支持以下操作:get 和 put。
get(key) - 如果键存在于缓存中,则获取键的值(总是正数),否则返回 -1。 put(key, value) -
如果键不存在,请设置或插入值。当缓存达到其容量时,它应该在插入新项目之前,使最不经常使用的项目无效。在此问题中,当存在平局(即两个或更多个键具有相同使用频率)时,最近最少使用的键将被去除。一个项目的使用次数就是该项目被插入后对其调用 get 和 put 函数的次数之和。使用次数会在对应项目被移除后置为 0。
进阶: 你是否可以在 O(1) 时间复杂度内执行两项操作?
示例:
LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ );
cache.put(1, 1); cache.put(2, 2); cache.get(1); // 返回 1
cache.put(3, 3); // 去除 key 2 cache.get(2); // 返回 -1 (未找到key 2)
cache.get(3); // 返回 3 cache.put(4, 4); // 去除 key 1
cache.get(1); // 返回 -1 (未找到 key 1) cache.get(3); // 返回 3
cache.get(4); // 返回 4
这题,,,,,实在不适合一个刚从周赛打完脑子还不清醒的菜鸡TWT,看了俩小时没找到从哪下手,问题在于如果用队列模拟活动顺序的话,索引需要不停的更换,如果用计数找最小值的话,会导致同值无法判断先后,因此把官方题解先拿来,有时候再细说这道题
class Node:
def __init__(self, key, val, pre=None, nex=None, freq=0):#这里是创建链表结构的初始化
self.pre = pre
self.nex = nex
self.freq = freq
self.val = val
self.key = key
def insert(self, nex):#创建插入方法
nex.pre = self
nex.nex = self.nex
self.nex.pre = nex
self.nex = nex
def create_linked_list():#建立一个空链表
head = Node(0, 0)
tail = Node(0, 0)
head.nex = tail
tail.pre = head
return (head, tail)
class LFUCache:
def __init__(self, capacity: int):#题目初始化
self.capacity = capacity
self.size = 0
self.minFreq = 0
self.freqMap = collections.defaultdict(create_linked_list)
self.keyMap = {}
def delete(self, node):#删除链表中的方法
if node.pre:
node.pre.nex = node.nex
node.nex.pre = node.pre
if node.pre is self.freqMap[node.freq][0] and node.nex is self.freqMap[node.freq][-1]:
self.freqMap.pop(node.freq)
return node.key
def increase(self, node):#插入链表方法
node.freq += 1
self.delete(node)
self.freqMap[node.freq][-1].pre.insert(node)
if node.freq == 1:
self.minFreq = 1
elif self.minFreq == node.freq - 1:
head, tail = self.freqMap[node.freq - 1]
if head.nex is tail:
self.minFreq = node.freq
def get(self, key: int) -> int:#获得时队列表进行循环移动
if key in self.keyMap:
self.increase(self.keyMap[key])
return self.keyMap[key].val
return -1
def put(self, key: int, value: int) -> None:#新元素进入时列表是否进行删除
if self.capacity != 0:
if key in self.keyMap:
node = self.keyMap[key]
node.val = value
else:
node = Node(key, value)
self.keyMap[key] = node
self.size += 1
if self.size > self.capacity:
self.size -= 1
deleted = self.delete(self.freqMap[self.minFreq][0].nex)
self.keyMap.pop(deleted)
self.increase(node)
#作者:LeetCode-Solution
#链接:https://leetcode-cn.com/problems/lfu-cache/solution/lfuhuan-cun-by-leetcode-solution/#
#来源:力扣(LeetCode)