思路分析

LRU(最近最少使用)的设计策略重点在于维护固定格式的缓存,这里用双向链表来维护这些缓存数据,更准确的来说是利用哈希表和双向链表来完成这一设计,哈希表的作用是在O(1)的时间内完成查找,双端链表则是用来保持按使用频率排序的操作,这个题目我们需要理解的是,如果进行了插入和取出,那么就要对缓存的数据进行排序。
因为数据既有key又有value,那么肯定需要使用到HashMap,并且我们如果插入或者取出数据后都要排序,并且set和get的时间复杂度都要是O(1),那么必须使用双向链表来维持缓存数据,因为如果是单向的链表删除数据的时候无法做到O(1)时间复杂度。

  1. class LRUCache {
  2. /*
  3. 定义一个Node
  4. */
  5. class Node{
  6. int key;
  7. int value;
  8. Node next;
  9. Node pre;
  10. public Node(int key, int value){
  11. this.key = key;
  12. this.value = value;
  13. }
  14. }
  15. //需要定义一个map
  16. private HashMap<Integer,Node> map;
  17. //定义缓存容量
  18. private int capacity;
  19. //定义头结点
  20. private Node head;
  21. //定义尾结点
  22. private Node tail;
  23. public LRUCache(int capacity) {
  24. //对这个cache进行初始化
  25. map = new HashMap<>();
  26. this.capacity = capacity;
  27. head = null;
  28. tail = null;
  29. }
  30. public int get(int key) {
  31. Node node = map.get(key);
  32. if(node==null){
  33. return -1;
  34. }
  35. //重新排序
  36. if(node!=tail){
  37. if(node==head){
  38. head = head.next;
  39. }else{
  40. node.pre.next = node.next;
  41. node.next.pre = node.pre;
  42. }
  43. tail.next = node;
  44. node.pre = tail;
  45. node.next = null;
  46. tail = node;
  47. }
  48. return node.value;
  49. }
  50. public void put(int key, int value) {
  51. Node node = map.get(key);
  52. if(node!=null){
  53. node.value = value;
  54. //重新排序
  55. if(node!=tail){
  56. if(node==head){
  57. head = head.next;
  58. }else{
  59. node.pre.next = node.next;
  60. node.next.pre = node.pre;
  61. }
  62. tail.next = node;
  63. node.pre = tail;
  64. node.next = null;
  65. tail = node;
  66. }
  67. }else{
  68. Node newNode = new Node(key, value);
  69. if(capacity==0){
  70. Node temp = head;
  71. head = head.next;
  72. if(temp==tail){
  73. tail = null;
  74. }
  75. map.remove(temp.key);
  76. capacity++;
  77. }
  78. if(head==null&&tail==null){
  79. head = newNode;
  80. }else{
  81. tail.next = newNode;
  82. newNode.pre = tail;
  83. newNode.next = null;
  84. }
  85. tail = newNode;
  86. map.put(key,newNode);
  87. capacity--;
  88. }
  89. }
  90. }
  91. /**
  92. * Your LRUCache object will be instantiated and called as such:
  93. * LRUCache obj = new LRUCache(capacity);
  94. * int param_1 = obj.get(key);
  95. * obj.put(key,value);
  96. */