LeetCode-146.LRU缓存机制
-
今天刷leetcode刷到非常有意思的题,让自己设计和实现一个LRU缓存机制,并且让在O(1)的时间复杂度完成。
-
首先了解一下LRU缓存机制,可参考这篇文章漫画:什么是LRU算法?
-
题目截图
-
解题思路
由于要求O(1)的复杂度,就需要用双向链表加hash进行实现。
每次get时,就将其所在的位置删除,并移到最前面去(Head头指针的后面)。
每次put时,需要进行判断,如果达到容量最大时,需要删除最后边的数据(Tail尾指针前边的元素),在将此数据加到最前边即可。否则,就直接添加到最前边即可。
-
代码实现
import java.util.HashMap; import java.util.Map; public class LRUCache { private class Node{ int key; int val; public Node(int key,int val){ this.key = key; this.val = val; } Node pre; Node next; } private int capacity; private Map<Integer,Node> map; private Node Head;//空头指针 private Node Tail;//空尾指针 public LRUCache(int capacity){ this.capacity = capacity; map = new HashMap(capacity); Head = new Node(-1,-1); Tail = new Node(-1,-1); Head.next = Tail; Tail.pre = Head; } //添加到头部 public void add(Node s){ Node headnext = Head.next; s.pre = Head; s.next = headnext; headnext.pre = s; Head.next = s; } //get到了,删除此节点 public void remove(Node s){ Node sTail = s.next; Node sHead = s.pre; sTail.pre = sHead; sHead.next = sTail; } //删除后面的结点 public void delTai(){ Node tlast = Tail.pre; tlast.pre.next = Tail; Tail.pre = tlast.pre; map.remove(tlast.key); } public int get(int key) { if(map.containsKey(key)){ Node result = map.get(key); remove(result); add(result); return result.val; } return -1; } public void put(int key, int value) { Node n = new Node(key,value); if(map.containsKey(key)) { Node s = map.get(key); map.put(key,n); remove(s); add(n); return; } if(map.size()==capacity){ delTai(); } map.put(key,n); add(n); } public static void main(String[] args) { // LRUcache cache = new LRUcache( 2 /* 缓存容量 */ ); // cache.get(2); // cache.put(2,6); // cache.get(1); // cache.put(1,5); // cache.put(1,2); // cache.get(1); // cache.get(2); // cache.put(1, 1); // cache.put(2, 2); // cache.get(1); // 返回 1 // cache.put(3, 3); // 该操作会使得密钥 2 作废 // cache.get(2); // 返回 -1 (未找到) // cache.put(4, 4); // 该操作会使得密钥 1 作废 // cache.get(1); // 返回 -1 (未找到) // cache.get(3); // 返回 3 // cache.get(4); // 返回 4 } }
-
官网题解给出一个运用LinkedHashMap的做法,由于一开始个人对LinkedHashMap不是很了解,了解之后,发现用的真是太妙了。官方题解代码
class LRUCache extends LinkedHashMap<Integer, Integer>{ private int capacity; public LRUCache(int capacity) { 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; } }