- 常数的时间复杂度:用hash字典
- 最久没用的关键字:要记录使用顺序,用队列
- 这里有问题:如果get()取得的是队列中间的关键字,此时要将其移到最后。时间复杂度不会是常数。单链表移动也不会是常数的时间复杂度,要用双向链表。
class LRUCache: # 不行的代码
def __init__(self, capacity: int):
self.capacity = capacity
self.dicts = collections.defaultdict(lambda:-1) # 默认-1
self.queue = []
self.count = 0
def get(self, key: int) -> int:
return self.dicts[key] # 没被put就默认返回-1
def put(self, key: int, value: int) -> None:
self.dicts[key] = value
self.count += 1
self.queue.insert(0, key)
if self.count > self.capacity:
tmpkey = self.queue.pop()
print(key)
self.count -= 1
self.dicts[tmpkey] = -1
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
- 双向链表+hash字典
class ListNode: # Ok的代码
def __init__(self, key=None, value=None, prev=None, next=None):
self.key = key
self.value = value
self.prev = prev
self.next = next
class LRUCache:
def __init__(self, capacity: int):
self.dicts = {}
self.capacity = capacity
self.head = ListNode()
self.tail = ListNode(prev=self.head)
self.head.next = self.tail
def move_to_end(self, key): # 根据键找到对应的链表结点
node = self.dicts[key]
# 将断点两边的结点连接上
if node.next and node.prev:# 如果是已经在链表中,还需断开
node.prev.next = node.next
node.next.prev = node.prev
# 将该节点插到最后的结点前
# 1.该节点连上去
node.next = self.tail
node.prev = self.tail.prev
# 2.该结点两边的连上
self.tail.prev.next = node
self.tail.prev = node
def get(self, key: int) -> int:
node = self.dicts.get(key, None) # 如果不存在返回None
if node:# 存在
# 将其移到最后去
self.move_to_end(key)
return node.value
else:
return -1
def put(self, key: int, value: int) -> None:
if key in self.dicts: # 如果已存在,更新value
self.dicts[key].value = value
else: # 不存在,插入
newnode = ListNode(key=key, value=value)
self.dicts[key] = newnode
# 移到最后,更新最新使用过
self.move_to_end(key)
if len(self.dicts) > self.capacity: # 超过容量,需删除最前面的最久没使用的结点
# 找到要删除的结点
node = self.head.next
# 删除字典中的该键值对
self.dicts.pop(node.key) # 这里就是node也要保存key的原因
# 删除双向链表中的该结点
self.head.next = node.next
node.next.prev = self.head
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
参考链接:数据结构分析,Python 哈希 + 双向链表实现(代码注释多)
如果比较模糊,建议动手画下。只要思路有了,实现就不是很难。