题目如下:
LRU:替换 最长时间没有使用的页面。
通过观察示例,我们会发现,每次get访问,都需要将 该节点的位置提前。
设计思路:用一个双端队列LinkedList (底层是双端链表)来作为 容器。
用HashMap来 映射 key 所在的node 节点。
每次访问或者最新插入的节点,我们放在队列的头部。LinkedList的addFirst() 方法添加。
那些很久没用的节点就会自动退到 队列的尾部。LinkedList的removeLast() 方法删除。
//先定义我们自己的数据结构node
class node {
int key;
int value;
public node(int key,int value) {
this.key=key;
this.value=value;
}
}
class LRUCache {
int capacity;
LinkedList<node> list =new LinkedList<>();
//存放key,和节点的位置,应该直接指向 节点的内存地址,用于get
Map<Integer,node> map= new HashMap<>();
//node节点所在LinkedList 中的位置,便于我们remove。
public LRUCache(int capacity) {
this.capacity=capacity;
}
public void put(int key, int value) {
//如果链表中没有它
//1.当前容量 < capacity,那直接插入双端链表即可。
//2.如果当前容量=capacity,正好满了,那就删除 链表最尾部的元素(它肯定是最久没有使用的),然后把新的元素添加进来。注意更新map
node n1 =new node(key,value);
if(!map.containsKey(key))
{
if(list.size()<capacity)
{
list.addFirst(n1);
map.put(key,n1);
}else if(list.size()==capacity)
{ //你替换一个元素的时候,得删掉map里的键值对。
node de=list.removeLast();
map.remove(de.key,de);
list.addFirst(n1);
map.put(key,n1);
}
}else {
//这个时候说明存在
node a=map.get(key);
list.remove(a);
list.addFirst(n1);
map.put(key,n1);
}
//如果当前链表中有它,那就删除 链表中的这个元素,再把新的元素头插法插入,这样能保证 这个元素最新进来。
}
}
public int get(int key) {
if(map.containsKey(key))
{
node n1=map.get(key);
int result =n1.value;
list.remove(n1);
list.addFirst(n1);
return result;
//因为get访问了这个元素,所以这个元素的位置要提到头部。
}else {
return -1;
}
}