LRU算法:是一种缓存淘汰策略,计算机的储存容量有限,储存满了就要删除一些内容,给新内容腾位置,删除没用的数据,保存有用的缓存。问题是如何进行删除和保留的选择。
LRU 缓存淘汰算法就是一种常用策略。LRU 的全称是 Least Recently Used,也就是说我们认为最近使用过的数据应该是是「有用的」,很久都没用过的数据应该是无用的,内存满了就优先删那些很久没用过的数据。
回归到具体算法:
LRU 算法实际上是让你设计数据结构:首先要接收一个 capacity 参数作为缓存的最大容量,然后实现两个 API,一个是 put(key, val) 方法存入键值对,另一个是 get(key) 方法获取 key 对应的 val,如果 key 不存在则返回 -1。
双链表:
class DoubleList{
private Node head,tail;//头尾虚节
private int size;//链表元素数
public DoubleList(){
head=new Node(0,0);
tail=new Node(0,0);
head.next=tail;//头的下一个是尾
tail.prev=head;//尾的下一个是头,构成双向链表
size=0;
}
//在头部添加节点
public void addFirst(Node x){
x.next=head.next;//双向链表添加阶段
x.prev=head;
head.next.prev=x;
head.next=x;
size++;
}
//删除链表中的x节点
public void remove(Node x){
x.prev.next=x.next;
x.next.prev=x.prev;
size--;
}
//删除最后一个节点,返回该节点
public Node removeLast(){
if(tail.prev==head)
return null;
Node last =tail.prev;
remove(last);
return last;
}
//返回链表长度
public int size(){
return size;
}
}
时间复杂度O(1)。
参考:https://leetcode-cn.com/problems/lru-cache/solution/lru-ce-lue-xiang-jie-he-shi-xian-by-labuladong/
解决方法2:
有序字典:综合哈希表和链表。
class LRUCache extends LinkedHashMap<Integer,Integer>{
private int capcity;
public LRUCache(int capcity){
super(capacity,0.75F,true);
this.capacity=capacity;
}
public int get(int key){
return super.getOrDefault(key,-1);
}
public void put(int key,int value){
super.put(key,value);
}
@Override
protected boolean removeEldestEntry(Map.Entry<Integer,Integer>eldest){
return size()>capacity;}
}