题目:146. LRU缓存机制 、面试题 16.25. LRU缓存
题目描述:
运用你所掌握的数据结构,设计和实现一个 LRU (Least Recently Used,最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put ,时间复杂度要求为O(1).
-
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
-
写入数据 put(key, value) - 如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
解题思路:哈希表+双向链表
LRU是Least Recently Used的简称,代表最近最少使用算法。对于get和put方法,实际上我们只需要取出对应的值和将键值对写入缓存即可,但是,关键的是如何组织数据空间,比如当缓存已满时,淘汰策略应该是最近最少使用的先删除。因此,需要对数据进行合理的组织。
所谓最近最少使用,当缓存容量已满时,需要选择那个最近最少使用的数据,将其删除,从而空出缓存空间。
该算法我们使用哈希表和双向链表两个数据结构来实现。其中哈希表主要用来保存键值对对应关系,而数据是否最近被使用过用一个双向链表来记录,排在双向链表靠前的代表最近刚被使用过,而排在后面的代表很久未使用,因此删除时从双向链表后端依次删除。
代码实现:
class LRUCache {
private Map<Integer,Integer> map;
private LinkedList<Integer> list;
private int sizeOfcache;
public LRUCache(int capacity) {
map=new HashMap<>(); //哈希表用于存储数据
list=new LinkedList<>(); //双向链表保存最近最少使用这一关系
this.sizeOfcache=capacity; //缓存容量
}
public int get(int key) {
if(map.containsKey(key)){
list.remove(Integer.valueOf(key)); //先从链表中删除
list.addFirst(key); //表示刚被访问过,越靠后表示最近最少使用的
return map.get(key);
}
return -1;
}
public void put(int key, int value) {
if(map.containsKey(key)) //已经存在,删掉
list.remove(Integer.valueOf(key));
else if(list.size()==sizeOfcache){ //不存在,且缓冲已满,删掉最后那个
int keyToRemove=list.removeLast();
map.remove(keyToRemove);
}
list.addFirst(key);
map.put(key,value);
}
}
/**
* 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);
*/