星期五,又是摸鱼的一天,那就整整活。
146. LRU 缓存机制
提示:
- 1 <= capacity <= 3000
- 0 <= key <= 3000
- 0 <= value <= 104
- 最多调用 3 * 104 次 get 和 put
思路
维护一个哈希表和一个双向链表。
关节是要点是哈希表里存的value是链表的一个node。
每个新加入的node或被操作过后的node,都放到链表最前面,那么排在最后面的node就是最久没被操作过的node。
当容量满了,就把链表最后一个node删除,再删除字典里对应的key-value,然后添加新node到链表头和字典里。
# python3
# 定义双向链表
class DLinkedNode:
def __init__(self, key = 0, value = 0, ):
self.val = value
self.key = key
self.next = None
self.pre = None
class LRUCache:
def __init__(self, capacity: int):
self.dic = dict()
self.head = DLinkedNode()
self.tail = DLinkedNode()
self.head.next = self.tail
self.tail.pre = self.head
self.size = 0
self.capacity = capacity
def get(self, key: int) -> int:
if key not in self.dic:
return -1
# 如果 key 存在,先通过哈希表定位,再移到头部
node = self.dic[key]
self.move_to_head(node)
return node.val
def put(self, key: int, value: int) -> None:
if key not in self.dic:
# 如果 key 不存在,创建一个新的节点
node = DLinkedNode(key, value)
# 添加进哈希表
self.dic[key] = node
# 添加到链表头部
self.add_to_head(node)
self.size += 1
# 如果容量已满
if self.size > self.capacity:
node_re = self.remove_tail()
self.dic.pop(node_re.key)
# 若不存在则加到链表头部和字典里
else:
node = self.dic[key]
node.val = value
self.move_to_head(node)
def remove_node(self, node:DLinkedNode):
node.pre.next = node.next
node.next.pre = node.pre
def add_to_head(self, node:DLinkedNode):
node.next = self.head.next
node.pre = self.head
self.head.next.pre = node
self.head.next = node
def remove_tail(self):
node = self.tail.pre
self.remove_node(node)
return node
def move_to_head(self, node:DLinkedNode):
self.remove_node(node)
self.add_to_head(node)
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)