补充知识:双向链表是什么?
OrderedDict如何理解?OrderedDict 是 Python 标准库 collections 模块中的一个字典子类,它会记住键值对插入的顺序。
个人感觉:"其实没必要去自己写代码实现OrderedDict,因为这个数据结构,本质就是用 双向链表+Dict实现,它主要满足的功能就是根据key找到对应的位置,并且完成修改这个key的位置的value,或者删除,其中找这个动作是dict实现,删除或者移动就是双向链表实现的"
1、解法1:python的 from collections import OrderedDict双向链表+哈希Dict的类
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = OrderedDict()
def get(self, key: int) -> int:
if key not in self.cache:
return -1
# 将访问的 key 移动到末尾(表示最近使用)
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key in self.cache:
# 更新并移动到末尾
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
# 弹出第一个元素(最久未使用)
self.cache.popitem(last=False)
2、解法2:
-自己实现OrderedDict
class Node:
"""双向链表节点"""
def __init__(self, key=0, value=0):
self.key = key
self.value = value
self.prev = None
self.next = None
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = {} # 哈希表:key -> 节点
# 使用伪头和伪尾节点,简化边界操作
self.head = Node() # 头节点(最久未使用)
self.tail = Node() # 尾节点(最近使用)
self.head.next = self.tail
self.tail.prev = self.head
def _add_node(self, node: Node) -> None:
"""在尾部添加节点(标记为最近使用)"""
node.prev = self.tail.prev
node.next = self.tail
self.tail.prev.next = node
self.tail.prev = node
def _remove_node(self, node: Node) -> None:
"""删除节点"""
node.prev.next = node.next
node.next.prev = node.prev
def _move_to_tail(self, node: Node) -> None:
"""将节点移动到尾部(标记为最近使用)"""
self._remove_node(node)
self._add_node(node)
def _pop_head(self) -> Node:
"""弹出头部节点(最久未使用)"""
node = self.head.next
self._remove_node(node)
return node
def get(self, key: int) -> int:
if key in self.cache:
node = self.cache[key]
self._move_to_tail(node) # 更新为最近使用
return node.value
return -1
def put(self, key: int, value: int) -> None:
if key in self.cache:
# 更新已有节点
node = self.cache[key]
node.value = value
self._move_to_tail(node)
else:
# 创建新节点
node = Node(key, value)
self.cache[key] = node
self._add_node(node)
# 如果超出容量,移除最久未使用的节点
if len(self.cache) > self.capacity:
lru_node = self._pop_head()
del self.cache[lru_node.key]