M-146. LRU Cache
# 其实思路很简单
# 首先, 两个类,
# 1. 一个Node类, 存k, v, prev和next
# 2. 一个cache类, 维护一个doublely链表(初始化是一个head一个tail相连),
# 一个cache字典, 装所有的{key: node} pair. 和一个cpacity变量存最大长度, 和一个size存当前长度.
# 1. put操作, 直接读cache, 如果有key存在, 更新node, 然后把node移到双列表head后面.
# 如果不存在, new一个, 然后写入cache字典, 并把它移动到双列表head后面. size+1,
# 如果此时size超过capacity, pop(tail.prev), 然后size-1. 然后cache字典里面的pair也要移除.
# 2. get操作, 直接读cache, 如果有key存在, 获取node.val, 然后把它移动到head后面; 如果
# 不存在, 返回-1.
# 所以我们需要的函数有:
# 1. 在head后增加该node
# 2. 在node处删除该node
# 3. 从链表尾部pop一个node然后返回(可以复用2)
# 4. 把已经存在的一个node移动到head后面(可以复用2和1)
# 5. 获取node
# 6. put node
class DLinkedNode():
def __init__(self, k = 0, v= 0):
self.key = k
self.value = v
self.prev = None
self.next = None
class LRUCache():
def _add_node(self, node):
"""
Always add the new node right after head.
"""
self.head.next, node.next = node, self.head.next
node.prev, node.next.prev = self.head, node
def _remove_node(self, node):
"""
Remove an existing node from the linked list.
"""
node.next.prev, node.prev.next = node.prev, node.next
def _move_to_head(self, node):
"""
Move certain node in between to the head.
"""
self._remove_node(node)
self._add_node(node)
def _pop_tail(self):
"""
Pop the current tail.
"""
res = self.tail.prev
self._remove_node(res)
return res
def __init__(self, capacity):
"""
:type capacity: int
"""
self.cache = {}
self.size = 0
self.capacity = capacity
self.head, self.tail = DLinkedNode(), DLinkedNode()
self.head.next = self.tail
self.tail.prev = self.head
def get(self, key):
"""
:type key: int
:rtype: int
"""
node = self.cache.get(key)
if not node:
return -1
# move the accessed node to the head;
self._move_to_head(node)
return node.value
def put(self, key, value):
"""
:type key: int
:type value: int
:rtype: void
"""
node = self.cache.get(key)
if not node:
newNode = DLinkedNode(key, value)
self.cache[key] = newNode
self._add_node(newNode)
self.size += 1
if self.size > self.capacity:
# pop the tail
tail = self._pop_tail()
self.cache.pop(tail.key)
self.size -= 1
else:
# update the value.
node.value = value
self._move_to_head(node)
Last updated
Was this helpful?