class Node:
def __init__(self, key=0, val=0, pre=None, next=None, fre=0, tail=None):
self.key = key
self.val = val
self.pre = pre
self.next = next
self.fre = fre
self.tail = tail
class LFUCache:
def __init__(self, capacity: int):
self.fre_to_node = {}
self.key_to_node = {}
self.length = 0
self.capacity = capacity
self.init_fre(1)
def init_fre(self, fre):
# 新建一個頻次的連結串列
head = Node()
tail = Node()
head.next = tail
tail.pre = head
self.fre_to_node[fre] = head
self.fre_to_node[fre].tail = tail
def insert(self, fre, node):
# 如果下一頻次的連結串列還不存在
if fre not in self.fre_to_node:
self.init_fre(fre)
# 插入新頻次連結串列的頭部
node.next = self.fre_to_node[fre].next
self.fre_to_node[fre].next.pre = node
self.fre_to_node[fre].next = node
node.pre = self.fre_to_node[fre]
# 更新節點的頻次值
node.fre = fre
def remove(self, node):
# 從雙向連結串列中刪除節點
node.pre.next = node.next
node.next.pre = node.pre
def show(self):
print("展示---------------")
index = 1
while index in self.fre_to_node:
print("頻率", index)
cur = self.fre_to_node[index].next
while cur != self.fre_to_node[index].tail:
print(cur.val, end="->")
cur = cur.next
print()
index += 1
print("鍵集合", self.key_to_node.keys())
print("結束---------------")
def get(self, key: int) -> int:
# 如果鍵不存在
if key not in self.key_to_node:
return -1
else:
# 如果鍵存在,把這個節點更新到下一頻次
node = self.key_to_node[key]
self.remove(node)
self.insert(node.fre + 1, node)
return node.val
def put(self, key: int, value: int) -> None:
# 如果鍵不存在
if key not in self.key_to_node:
# LFU未滿
if self.length < self.capacity:
node = Node(key=key, val=value, fre=1)
self.insert(1, node)
self.key_to_node[key] = node
self.length += 1
else:
# LFU已滿
index = 1
while index in self.fre_to_node:
if self.fre_to_node[index].next != self.fre_to_node[index].tail:
break
index += 1
t = self.fre_to_node[index].tail.pre
del self.key_to_node[t.key]
self.remove(t)
node = Node(key=key, val=value, fre=1)
self.insert(1, node)
self.key_to_node[key] = node
else:
# 如果鍵存在,只需要更新鍵值,把節點更新到下一頻次
node = self.key_to_node[key]
node.val = value
self.remove(node)
self.insert(node.fre + 1, node)
# Your LFUCache object will be instantiated and called as such:
# obj = LFUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)