LRU缓存
本题中要求插入数据以及获取数据都需要* O(1)* 的平均时间复杂度运行,因此借用了哈希表和双向链表
其中哈希表用于快速定位节点
双向链表用于维护一个链表来准确找出最近最少使用的节点,具体实现逻辑如下
- 假如用户get了该节点,那么在双向链表中删除该节点,然后插入到头节点中,因此尾节点就是最近最少使用的节点
- 假如说现在LRU中满了,那么拿出尾节点前面前面的节点删掉即可满足要求
public class LRUCache {
class Node{
int key;
int value;
Node pre;
Node next;
public Node(int key,int value){
this.key = key;
this.value = value;
}
}
int capacity;
int size = 0;
HashMap<Integer,Node> map = null;
Node head;
Node tail;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>(capacity);
head = new Node(0,0);
tail = new Node(0,0);
head.next = tail;
tail.pre = head;
}
public int get(int key) {
if (map.containsKey(key)){
Node node = map.get(key);
// 删除然后插入头节点
removeCache(key);
// 插入头节点
insertHead(key,node.value);
return node.value;
}else{
return -1;
}
}
private void insertHead(int key, int value) {
Node node = new Node(key,value);
node.next = head.next;
node.pre = head;
node.next.pre = node;
head.next = node;
this.size++;
map.put(key,node);
if (this.size > this.capacity){
int deletedKey = tail.pre.key;
removeCache(deletedKey);
}
}
private void removeCache(Integer key) {
Node node = map.get(key);
Node pre = node.pre;
Node nex = node.next;
pre.next = nex;
nex.pre = pre;
this.size--;
map.remove(key);
}
public void put(int key, int value) {
if (map.containsKey(key)){
removeCache(key);
insertHead(key,value);
}else{
insertHead(key,value);
}
}
}