第一次看到这个题目,我懵逼了,啥是LRU,因而乎我去百度了一下,大概的意思是这样的,LRU是Least Recently Used的缩写,即最近最少使用,选择最近最久未使用的key予以淘汰。 大概了解后我想到(实际想了半天。。。而且还参考了网上的其余人的一些思路)node
既然要频繁的删除和插入,那确定首选链表,大概思路分以下几步: 1.须要一个双向链表,头节点和尾节点 2.HashMap存储key, HashMap的Value为双向链表LRU的Node节点 3.put插入时判断该key是否存在,若是不存在,再判断是否空间满了,满了就删除末尾节点(最少使用节点),而后把新插入元素放到头节点,若是没满则插入到链表头节点,若是已存在,则移动该节点到头节点 4.get获取节点时有则返回,而且把该节点移动到链表的头节点bash
代码实现以下:测试
/**
* 双向链表
*/
class LinkNode {
/**
* 前节点
*/
LinkNode pre;
/**
* 后节点
*/
LinkNode next;
int key;
int val;
}
public class LRUCache {
private int capacity;
private LinkNode head;
private LinkNode tail;
private HashMap<Integer,LinkNode> cache;
public LRUCache(int capacity) {
this.capacity=capacity;
cache = new HashMap<>(capacity);
}
public int get(int key) {
LinkNode res = cache.get(key);
if(res == null){
return -1;
}
moveNodeToFirst(res);
return res.val;
}
public void put(int key, int value) {
LinkNode tempLinkNode = cache.get(key);
if(tempLinkNode == null){
if(cache.size() >= capacity){
removeLastNode();
}
tempLinkNode = new LinkNode();
tempLinkNode.key = key;
}
tempLinkNode.val = value;
moveNodeToFirst(tempLinkNode);
cache.put(key, tempLinkNode);
}
/**
* put或者get时移动该节点到链表的头节点
* @param node
*/
private void moveNodeToFirst(LinkNode node) {
//空链表时放入第一个元素
if(head == null){
tail = head = node;
return;
}
//链表的头部
if (head == node) {
return;
}
//链表的尾部
else if(tail == node){
//把他前面的节点变成尾节点(他要被移动到链表开头了)
tail = tail.pre;
}
//在链表中间的节点
else if(node.next != null || node.pre != null){
//节点被移动到头部后,相邻节点的先后节点值变化
assert node.pre != null;
node.pre.next = node.next;
assert node.next != null;
node.next.pre = node.pre;
}
//原来的链表头部,变成第二个
node.next = head;
//节点被移动到头部后,相邻节点的先后节点值变化
head.pre = node;
//放到头部后他的前节点为空
node.pre = null;
//放到链表头部
head = node;
}
/**
* 超过hashMap容量时删除最后一个元素,即最少使用元素
*/
private void removeLastNode() {
LinkNode tempLinkNode = tail;
//倒数第二个节点变成最后一个节点
tail = tail.pre;
if(tail != null){
tail.next = null;
}else{
head = null;
}
cache.remove(tempLinkNode.key);
}
}
复制代码
测试ui
public static void main(String[] args) {
LRUCache cache = new LRUCache( 2 );
cache.put(1, 1);
cache.put(2, 2);
System.out.println("获取1的值" + cache.get(1));
cache.put(3, 3);
System.out.println("key:3已插入, key:2,被删除");
System.out.println("获取2的值" + cache.get(2));
cache.put(4, 4);
System.out.println("key:4已插入, key:1,被删除");
System.out.println("获取1的值" + cache.get(1));
System.out.println("获取3的值" + cache.get(3));
System.out.println("获取4的值" + cache.get(4));
}
复制代码
结果this
获取1的值:1
key:3已插入, key:2,被删除
获取2的值:-1
key:4已插入, key:1,被删除
获取1的值-1
获取3的值:3
获取4的值:4
复制代码
参考资料:cloud.tencent.com/developer/a… www.jianshu.com/p/34c03210c…spa