题目描述
题目分析
- 首先是LRU缓存思想,LRU(Least Recently Used,最近最少使用),顾名思义,是淘汰最近最少使用的项目,其思想是如果数据最近被访问过,那么将来被访问的几率更高
- 此时第一个想的是使用一个链表,最近使用的放在最后面,最近没用的放在最前面,来了一个新的数,就判断内存是否满了,把最旧的数淘汰再加入新数。为了方便移动数据,应该使用链表。
- 对于这个问题,一共有两个需求,第一个是对链表中的数据进行更新,另一个需求是判断要加入的数据是否已经存在链表当中
- 对链表数据进行更新,除了删除,插入还有把数据从中间取出放到末尾(链表中存在数据的情况)
- 综上,最合适的应该是使用LinkedHashMap,使用map是为了判断数据在不在链表中。
题目解答
使用了LinkedHashMap或者双向链表+HashMap作为数据结构来进行解决,当然也可以使用单链表来进行解决。
class LRUCache {
int capacity;
Map<Integer,Integer> map;
public LRUCache(int capacity) {
this.capacity=capacity;
map=new LinkedHashMap(capacity);
}
public int get(int key) {
if(!map.containsKey(key)){
return -1;
}
//先删除旧位置,再放入新位置
//因为使用了所以更新位置,把元素放到末尾
Integer value=map.remove(key);
map.put(key,value);
return value;
}
public void put(int key, int value) {
if(map.containsKey(key)){
//如果存在就更新位置
map.remove(key);
map.put(key,value);
return;
}
//不存在时直接删除第一个元素再插入
map.put(key,value);
if(map.size()>capacity){
map.remove(map.entrySet().iterator().next().getKey());
}
}
}
class LRUCache {
//定义一个双向链表
public class ListNode{
int key;
int value;
ListNode pre;
ListNode next;
public ListNode(int key,int value){
this.key=key;
this.value=value;
pre=null;
next=null;
}
}
private int capacity;
private Map<Integer,ListNode> map;
private ListNode head;
private ListNode tail;
public LRUCache(int capacity) {
this.capacity=capacity;
map=new HashMap<>();
head=new ListNode(-1,-1);
tail=new ListNode(-1,-1);
head.next=tail;
tail.pre=head;
}
public int get(int key) {
if(!map.containsKey(key)) return -1;
//如果结点存在,先把他删除,再放到最后一位
ListNode node=map.get(key);
node.pre.next=node.next;
node.next.pre=node.pre;
moveToTail(node);
return node.value;
}
public void put(int key, int value) {
//直接调用get方法,如果存在,就会在get内部被拖动到最后
if(get(key)!=-1){
map.get(key).value=value;
return;
}
//不存在,就new一个出来放进去
ListNode node=new ListNode(key,value);
map.put(key,node);
moveToTail(node);
//如果超出容量,就去掉它的头
if(map.size()>capacity){
map.remove(head.next.key);
head.next=head.next.next;
head.next.pre=head;
}
}
private void moveToTail(ListNode node){
node.pre=tail.pre;
tail.pre=node;
node.pre.next=node;
node.next=tail;
}
}