题目链接:https://leetcode.cn/problems/lru-cache/
难度:中等

描述:
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

题解

  1. class DLinkedNode:
  2. def __init__(self, key=0, value=0):
  3. self.key = key
  4. self.value = value
  5. self.prev = None
  6. self.next = None
  7. class LRUCache:
  8. def __init__(self, capacity: int):
  9. self.cache = dict()
  10. # 使用伪头部和伪尾部节点
  11. self.head = DLinkedNode()
  12. self.tail = DLinkedNode()
  13. self.head.next = self.tail
  14. self.tail.prev = self.head
  15. self.capacity = capacity
  16. self.size = 0
  17. def get(self, key: int) -> int:
  18. if key not in self.cache:
  19. return -1
  20. # 如果 key 存在,先通过哈希表定位,再移到头部
  21. node = self.cache[key]
  22. self.moveToHead(node)
  23. return node.value
  24. def put(self, key: int, value: int) -> None:
  25. if key not in self.cache:
  26. # 如果 key 不存在,创建一个新的节点
  27. node = DLinkedNode(key, value)
  28. # 添加进哈希表
  29. self.cache[key] = node
  30. # 添加至双向链表的头部
  31. self.addToHead(node)
  32. self.size += 1
  33. if self.size > self.capacity:
  34. # 如果超出容量,删除双向链表的尾部节点
  35. removed = self.removeTail()
  36. # 删除哈希表中对应的项
  37. self.cache.pop(removed.key)
  38. self.size -= 1
  39. else:
  40. # 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
  41. node = self.cache[key]
  42. node.value = value
  43. self.moveToHead(node)
  44. def addToHead(self, node):
  45. node.prev = self.head
  46. node.next = self.head.next
  47. self.head.next.prev = node
  48. self.head.next = node
  49. def removeNode(self, node):
  50. node.prev.next = node.next
  51. node.next.prev = node.prev
  52. def moveToHead(self, node):
  53. self.removeNode(node)
  54. self.addToHead(node)
  55. def removeTail(self):
  56. node = self.tail.prev
  57. self.removeNode(node)
  58. return node