class Node:
def __init__(self, key=0, value=0):
self.key = key
self.value = value
self.freq = 1
self.prev = None
self.next = None
class LinkedList:
def __init__(self):
self.head = Node()
self.tail = Node()
self.head.next = self.tail
self.tail.prev = self.head
self.size = 0
def remove(self, node):
node.prev.next = node.next
node.next.prev = node.prev
self.size -= 1
def add_front(self, node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
self.size += 1
class LFUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.size = 0
self.freq_to_node = dict()
self.dict_of_nums = dict()
self.min_freq = 0
def get(self, key: int) -> int:
if key not in self.dict_of_nums:
return -1
node_to_update = self.dict_of_nums[key]
freq_node_to_update = node_to_update.freq
self.freq_to_node[freq_node_to_update].remove(node_to_update)
if self.freq_to_node[freq_node_to_update].size == 0 and freq_node_to_update == self.min_freq:
self.min_freq += 1
node_to_update.freq = freq_node_to_update + 1
if node_to_update.freq not in self.freq_to_node:
self.freq_to_node[node_to_update.freq] = LinkedList()
self.freq_to_node[node_to_update.freq].add_front(node_to_update)
return node_to_update.value
def put(self, key: int, value: int) -> None:
if key in self.dict_of_nums:
node = self.dict_of_nums[key]
node.value = value
self.get(key)
return
if self.size + 1 > self.capacity:
linked_list = self.freq_to_node[self.min_freq]
node_to_remove = linked_list.tail.prev
self.freq_to_node[self.min_freq].remove(node_to_remove)
del self.dict_of_nums[node_to_remove.key]
self.size -= 1
node = Node(key, value)
self.dict_of_nums[key] = node
self.min_freq = 1
if 1 not in self.freq_to_node:
self.freq_to_node[self.min_freq] = LinkedList()
self.freq_to_node[self.min_freq].add_front(node)
self.size += 1
# Your LFUCache object will be instantiated and called as such:
# obj = LFUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)