146. LRU 缓存
class ListNode:
def __init__(self, key=None, value=None):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.hashmap = {}
# 新建两个节点 head 和 tail
self.head = ListNode()
self.tail = ListNode()
self.head.next = self.tail
self.tail.prev = self.head
def move_node_to_tail(self, key):
node = self.hashmap[key]
node.prev.next = node.next
node.next.prev = node.prev
node.prev = self.tail.prev
node.next = self.tail
self.tail.prev.next = node
self.tail.prev = node
def get(self, key: int) -> int:
if key in self.hashmap:
self.move_node_to_tail(key)
res = self.hashmap.get(key, -1)
if res == -1:
return res
else:
return res.value
def put(self, key: int, value: int) -> None:
if key in self.hashmap:
self.hashmap[key].value = value
self.move_node_to_tail(key)
else:
if len(self.hashmap) == self.capacity:
self.hashmap.pop(self.head.next.key)
# 去掉最久没有被访问过的节点,即头节点之后的节点
self.head.next = self.head.next.next
self.head.next.prev = self.head
new = ListNode(key, value)
self.hashmap[key] = new
new.prev = self.tail.prev
new.next = self.tail
self.tail.prev.next = new
self.tail.prev = new
在move_node_to_tail函数中:
node.prev.next = node.next 和 node = node.next 是两种完全不同的操作。
node.prev.next = node.next 是在修改链表的结构。具体来说,它是在将 node 节点从链表中移除。node.prev.next 表示的是 node 的前一个节点的 next 指针,node.next 表示的是 node 的下一个节点。这行代码的作用是将 node 的前一个节点的 next 指针指向 node 的下一个节点,从而跳过 node,达到移除 node 的效果。
而 node = node.next 是在移动 node 指针。它将 node 指针指向当前 node 的下一个节点。这个操作并不会改变链表的结构,只是改变 node 指针的位置。
所以,node.prev.next = node.next 和 node = node.next 在功能上是完全不同的,前者是用来修改链表结构的,后者是用来移动指针的。