146. LRU 缓存 - Java 双向链表+哈希表
                
            
             
        
            
            原题地址:https://leetcode.cn/problems/lru-cache/ 
题解
LRU缓存本质上是手搓一个双向链表,并结合哈希表映射实现LRU的更新
当我们向双向链表中添加一个节点时,也创建一个<Integer,ListNode>的键值对,以便我们迅速地通过关键字在链表中找到对应节点
对于链表,我们规定越靠前的元素越少被使用
当一个Key被使用(包括查询和更新)时,我们需要进行一次操作:找到链表中Key对应的节点,并将其从链表中删除,然后重新添加到链表末尾
refresh操作:
- 找到链表中Key对应的节点,并将其从链表中删除,然后重新添加到链表末尾
 
- 用于指示该关键字是最近被使用
 
get操作:
- 在哈希表中查找是否存在关键字
 
- 若存在,则对关键字进行refresh操作,然后返回value值
 
- 若不存在,则返回-1
 
put操作:
- 在哈希表中查找是否存在关键字
- 若存在,则对关键字指向节点的value进行更新,并对关键字进行refresh操作
 
 
- 若不存在,则检查双向链表的长度是否达到capacity
- 若已达到容量,则删除表中的第一个元素,并移除哈希表中的键值对,指示该关键字已被删除
 
 
- 将新节点加入表尾,并添加关键字和节点的键值对
 
时间复杂度:O(1)
空间复杂度:O(N)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
   | class LRUCache {     class ListNode{         int key;         int val;         ListNode next;         ListNode last;         ListNode(int k,int v){             this.key=k;             this.val=v;         }     }          Map<Integer,ListNode> idx=new HashMap<>();          ListNode head=new ListNode(0,0);     ListNode tail=head;     int capacity;     void removeNode(ListNode node){         if(node==tail){             tail=node.last;             tail.next=null;         }else{             node.last.next=node.next;             node.next.last=node.last;         }         head.val--;     }     void addNode(ListNode node){         tail.next=node;         node.last=tail;         tail=tail.next;         tail.next=null;         head.val++;     }     void refreshKey(int key){         removeNode(idx.get(key));         addNode(idx.get(key));     }
      public LRUCache(int capacity) {         this.capacity=capacity;     }
           public int get(int key) {         if(idx.containsKey(key)){             refreshKey(key);             return idx.get(key).val;         }         else return -1;     }
      public void put(int key, int value) {                  if(idx.containsKey(key)){             idx.get(key).val=value;             refreshKey(key);         }else{                          if(head.val>=capacity){                 idx.remove(head.next.key);                 removeNode(head.next);             }                          addNode(new ListNode(key,value));             idx.put(key,tail);         }     } }
  |