1.题目描述

2.思路
LRU(最近最少使用):如果缓存的容量为2,刚开始的两个元素都入栈。之后该2元素中有其中一个元素(重点元素)被访问。把最近访问过的重点元素保留,另一个边缘元素就得离开缓存了。
下面是leetcode思路:
总结:
(1)创建一个哈希表和双向链表。链表头部是最近刚使用过的元素,尾部是最近不经常使用的元素。
(2)put(),首先如果新加入的元素在哈希表中不存在,则直接创建新节点加入到map中。如果双向链表的节点数超过链表容量,则剔除尾部节点(包括它的值)。如果新加入的元素存在(key存在),我们通过get进行定位,把节点值进行更新,移动到头部(说明是最近刚被访问的)
(3)get(),如果get(key)不存在直接返回-1,如果key存在,说明key节点是最近被使用的节点。通过哈希表定位到双向链表的位置,并将其移动到双向链表的头部,返回该节点的值。
3.代码实现
java
class LRUCache {
class doubleLinkedNode{
int key;
int value;
doubleLinkedNode prev;
doubleLinkedNode next;
public doubleLinkedNode() {
}
public doubleLinkedNode(int key, int value) {
this.key = key;
this.value = value;
}
}
private Map<Integer,doubleLinkedNode> cache=new HashMap<Integer,doubleLinkedNode>();
private int size;
private int capacity;
private doubleLinkedNode head;
private doubleLinkedNode tail;
public LRUCache(int capacity) {
this.size=0;
this.capacity=capacity;
//使用伪头部和伪尾部节点
head=new doubleLinkedNode();
tail=new doubleLinkedNode();
head.next=tail;
tail.prev=head;
}
public int get(int key) {
doubleLinkedNode node=cache.get(key);
if(node==null)
{
return -1;
}
//如果key存在,通过哈希表定位,再移动到头部
moveToHead(node);
return node.value;
}
public void put(int key, int value) {
doubleLinkedNode node=cache.get(key);
if(node==null)
{
//2.如果key不存在,则创建一个新的节点
doubleLinkedNode newNode=new doubleLinkedNode(key,value);
//添加到哈希表
cache.put(key,newNode);
//添加到双向链表的头部
addToHead(newNode);
size++;
// 如果添加的数量超出容量
if(size>capacity)
{
//超出容量,说明要删除双向链表的尾部节点
doubleLinkedNode tail=removeTail();
//删除哈希表中对应的项,删尾部节点对应的key值
cache.remove(tail.key);
size--;
}
}
else{
//如果key存在,先通过哈希表定位,再修改value,并移动到头部
node.value=value;
moveToHead(node);
}
}
private void addToHead(doubleLinkedNode node)
{
node.prev=head;
node.next=head.next;
head.next.prev=node;
head.next=node;
}
private void removeNode(doubleLinkedNode node)
{
node.prev.next=node.next;
node.next.prev=node.prev;
}
private void moveToHead(doubleLinkedNode node)
{
removeNode(node);
addToHead(node);
}
private doubleLinkedNode removeTail()
{
doubleLinkedNode res=tail.prev;
removeNode(res);
return res;
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/