设计和实现用于最近最少使用(LRU)缓存的数据结构,该结构支持get和put。
分析
解决此问题的关键是使用双链表,该链表使我们能够快速移动节点。
LRU缓存是键和双链接节点的哈希表。哈希表使get()的时间为O(1)。双向链接节点列表使节点添加/删除操作为O(1)。
Java解决方案
定义一个双链表。
class Node{
int key;
int value;
Node prev;
Node next;
public Node(int key, int value){
this.key=key;
this.value=value;
}
}
通过分析获取和放置,我们可以总结出两个基本操作:
- 1)removeNode(Node t)
- 2)offerNode(Node t)
class LRUCache {
Node head;
Node tail;
HashMap<Integer, Node> map = null;
int cap = 0;
public LRUCache(int capacity) {
this.cap = capacity;
this.map = new HashMap<>();
}
public int get(int key) {
if(map.get(key)==null){
return -1;
}
//move to tail
Node t = map.get(key);
removeNode(t);
offerNode(t);
return t.value;
}
public void put(int key, int value) {
if(map.containsKey(key)){
Node t = map.get(key);
t.value = value;
//move to tail
removeNode(t);
offerNode(t);
}else{
if(map.size()>=cap){
//delete head
map.remove(head.key);
removeNode(head);
}
//add to tail
Node node = new Node(key, value);
offerNode(node);
map.put(key, node);
}
}
private void removeNode(Node n){
if(n.prev!=null){
n.prev.next = n.next;
}else{
head = n.next;
}
if(n.next!=null){
n.next.prev = n.prev;
}else{
tail = n.prev;
}
}
private void offerNode(Node n){
if(tail!=null){
tail.next = n;
}
n.prev = tail;
n.next = null;
tail = n;
if(head == null){
head = tail;
}
}
}