2020.04.05
今天的题目是一道设计类的题目。和146题LRU缓存机制很类似。并且在解题的设计思路上我确实借鉴了设计思路。
这一类的题目难点都是在存储机制存储满以后如何实现在
O
(
1
)
O(1)
O(1)的时间复杂度里面删除元素。
LRU删除元素的操作顺序是删除最久没有使用的,因此采用链表的形式,每次删除头节点就可以。
LFU是删除频次最低的,同频次下删除最久没使用的,因此我们需要得到最低频次的数据是哪些。
设计思路是,字典+双向链表,链表存储一个有序字典和对应的频率数值。
每次进行操作,都将该键值对移动到象征更高频次的节点的有序字典的末尾进行存储。
在进行删除操作时,得到用户的头节点也就是象征最低访问频次的节点,删除该节点中有序字典的头一个键值对即可。
代码如下:
class Listnode():
def __init__(self, fre = None):
self.num = fre
self.dic = collections.OrderedDict()
self.next = None
self.pre = None
class LFUCache(object):
def __init__(self, capacity):
"""
:type capacity: int
"""
self.dic = {}
self.star = Listnode(0)
self.end = Listnode(float('inf'))
self.star.next = self.end
self.end.pre = self.star
self.capacity = capacity
def move(self, node, key): # 频率加一
if node.next.num == node.num + 1:
node.next.dic[key] = node.dic[key]
node.dic.pop(key)
self.dic[key] = node.next
else:
new_node = Listnode(node.num+1)
new_node.next = node.next
node.next.pre = new_node
new_node.pre = node
node.next = new_node
new_node.dic[key] = node.dic[key]
node.dic.pop(key)
self.dic[key] = new_node
if len(node.dic) == 0:
node.pre.next = node.next
node.next.pre = node.pre
def delet(self): # 删除最低使用频次的节点
node = self.star.next
#if len(node.dic) == 0:
# return
if len(node.dic) == 1:
self.star.next = node.next
node.next.pre = self.star
[key, value] = node.dic.popitem(last=False)
else:
[key, value] = node.dic.popitem(last=False)
return key
def get(self, key):
"""
:type key: int
:rtype: int
"""
if key not in self.dic:
return -1
node = self.dic[key]
value = node.dic[key]
self.move(node, key)
return value
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: None
"""
#三种情况:1.在册,2.不在册未满员,3.不在册,且满员
if key in self.dic:
node = self.dic[key]
node.dic[key] = value
self.move(node, key)
else:
if self.capacity == 0:
return
if len(self.dic) == self.capacity:
delkey = self.delet()
print(delkey)
self.dic.pop(delkey)
if self.star.next.num == 1:
node = self.star.next
node.dic[key] = value
self.dic[key] = node
else:
node = Listnode(1)
self.star.next.pre = node
node.next = self.star.next
self.star.next = node
node.pre = self.star
self.dic[key] = node
node.dic[key] = value
# Your LFUCache object will be instantiated and called as such:
# obj = LFUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)