LRU cache为最近最少使用,
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
思路: 我们可以用一个字典来实现该数据结构,因为字典的查找是O(1),字典的key就是LRU cache的key, 而字典的value可以用一个双向链表来表示,设其数据结构为node, 那么node中含有实际需要的key和value, 除此之外,还需要一个指向其前一个结果和后一个结点的指针,这样可以在O(1)的时间把链表的某个结点删除或移动到首部。 即字典的key是cache的key, 字典的value是一个双向链表, node中之所以需要存储key,是因为从LRU中更新时,删除最后一个节点时,需要找到其字典中对应的key
题目链接:LRU 缓存
class ListNode:
def __init__(self, key=0, value=0):
self.key = key
self.value = value
self.next = None
self.prev = None
class LRUCache:
def __init__(self, capacity: int):
self.dummy = ListNode() ## 最新的key 在 dummy 的next 节点,最旧的key 在 prev 节点
self.dummy.next = self.dummy.prev = self.dummy
self.capacity = capacity
self.key_to_node = dict() ## 存放 lru 的 key, value 是 ListNode
def delete(self, key):
node1 = self.key_to_node[key]
node1.next.prev = node1.prev
node1.prev.next = node1.next
node1.prev = node1.next = None
del self.key_to_node[key]
def append(self, key, value):
## 更新链表(插入到 dummy 的 next 节点)和 key_to_node
node1 = ListNode(key, value)
node1.next = self.dummy.next
self.dummy.next.prev = node1
self.dummy.next = node1
node1.prev = self.dummy
self.key_to_node[key] = node1
def get(self, key: int) -> int:
#print(self.key_to_node)
if key in self.key_to_node:
## 先删除 key, 再插入到 dummy next 节点(更新lru 顺序)
node1 = self.key_to_node[key]
self.delete(key)
self.append(key, node1.value)
return node1.value
else:
return -1
def put(self, key: int, value: int) -> None:
#print(self.key_to_node)
if key in self.key_to_node:
self.delete(key)
self.append(key, value)
else:
## 如果 cache 已经满了, 删除 dummy 的 prev 节点
if len(self.key_to_node) == self.capacity:
self.delete(self.dummy.prev.key)
self.append(key, value)
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)