请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。 void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。 函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。

分析

关注:

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

以O(1)的时间复杂度进行get和put,数据结构需采用双向链表+Map

自定义链表

初始化
image.png

  • 易错点1:链表的引用关系,移除了链表的节点后,引用关系发生改变,map需要重新put新的引用节点
  • [x] 易错点2:链表的引用关系,移除了链表的节点后,引用关系发生改变,map需要重新put新的引用节点

    1. class LRUCache {
    2. DLink dLink;
    3. Map<Integer,Node> map;
    4. int cap;
    5. public LRUCache(int capacity) {
    6. dLink = new DLink();
    7. map = new HashMap<>();
    8. this.cap = capacity;
    9. }
    10. public int get(int key) {
    11. if (map.containsKey(key)){
    12. int val = map.get(key).val;
    13. put(key,val);
    14. return val;
    15. }
    16. return -1;
    17. }
    18. public void put(int key, int value) {
    19. Node node = new Node(key,value);
    20. if (map.containsKey(key)){
    21. dLink.remove(map.get(key));
    22. dLink.addHead(node);
    23. map.put(key,node); //易错点1
    24. }else {
    25. if (map.size() == cap){
    26. int oldKey = dLink.remove(dLink.tail.pre);
    27. map.remove(oldKey);
    28. }
    29. map.put(key,node); //易错点2
    30. dLink.addHead(node);
    31. }
    32. }
    33. class Node {
    34. int key;
    35. int val;
    36. Node next = null;
    37. Node pre = null;
    38. public Node(int key,int val) {
    39. this.key = key;
    40. this.val = val;
    41. }
    42. }
    43. class DLink {
    44. Node head;
    45. Node tail;
    46. public DLink() {
    47. this.head = new Node(-1,-1);
    48. this.tail = new Node(-1,-1);
    49. head.next = tail;
    50. tail.pre = head;
    51. }
    52. public void addHead(Node node){
    53. node.next = head.next;
    54. node.pre = head;
    55. head.next.pre = node;
    56. head.next = node;
    57. }
    58. public int remove(Node node){
    59. node.pre.next = node.next;
    60. node.next.pre = node.pre;
    61. node.pre = null;
    62. node.next = null;
    63. return node.key;
    64. }
    65. }
    66. }

    易错点图示

    image.png