LRU
https://leetcode.cn/problems/lru-cache/description/?envType=study-plan-v2&envId=top-100-liked
class LRUCache {
HashMap<Integer,DLinkedNode> map;
int dLinkSize;
int capacity;
DLinkedNode head;
DLinkedNode tail;
class DLinkedNode{
int key;
int value;
DLinkedNode prior;
DLinkedNode next;
public DLinkedNode(){ }
public DLinkedNode(int key,int value){
this.key = key;
this.value = value;
}
}
public LRUCache(int capacity) {
this.map = new HashMap<>();
this.dLinkSize = 0;
this.capacity = capacity;
this.head = new DLinkedNode();
this.tail = new DLinkedNode();
head.next = tail;
tail.prior = head;
}
public int get(int key) {
if (map.containsKey(key)){
DLinkedNode node = map.get(key);
moveNodeToHead(node);
return node.value;
}else {
return -1;
}
}
public void put(int key, int value) {
if (map.containsKey(key)){
DLinkedNode node = map.get(key);
node.value = value;
moveNodeToHead(node);
}else if (dLinkSize < capacity){
DLinkedNode newNode = addNodeHead(key,value);
map.put(key,newNode);
}else {
int curKey = deleteTailNode();
map.remove(curKey);
DLinkedNode newNode = addNodeHead(key,value);
map.put(key,newNode);
}
}
private DLinkedNode addNodeHead(int key,int value){
DLinkedNode node = new DLinkedNode(key,value);
moveNodeToHeadHelper(node);
dLinkSize++;
return node;
}
private void moveNodeToHead(DLinkedNode node){
removeNode(node);
moveNodeToHeadHelper(node);
}
private int deleteTailNode(){
int key = tail.prior.key;
removeNode(tail.prior);
dLinkSize--;
return key;
}
private void removeNode(DLinkedNode node){
node.prior.next = node.next;
node.next.prior = node.prior;
}
private void moveNodeToHeadHelper(DLinkedNode node){
node.next = head.next;
head.next.prior = node;
head.next = node;
node.prior = head;
}
}
总结: 用hashmap存key和链表节点,双向链表的头代表新的或刚使用的,双向链表的尾代表要删除的。双向链表维护虚拟头结点,虚拟尾结点来统一操作。 要注意put的判断,要先看key在不在map中,而不是先看链表长度是不是小于容量,因为会发生链表长度没到容量,但是map中已经存在key,想要覆盖的情况,这个是我踩过的坑。
标签:node,map,int,DLinkedNode,value,LRU,key From: https://www.cnblogs.com/jeasonGo/p/18104549