146. LRU 缓存
自己造轮子
class LRUCache {
// 题根据目要求函数 get 和 put 必须以 O(1) 的平均时间复杂度运行,所以一定需要用到HashMap。
// 同时,需要删除最久未使用,也就是说需要保留顺序,需要用到队列,并且插入删除复杂度O(1),所以需要用到链表(双向)实现的队列
// 综上所述,需要设计一个LinkedHashMap这样的类
// key -> Node(key,val)
private HashMap<Integer,Node> map;
// Node(k1,v1) <-> Node(k2,v2)
private DoubleList cache;
// 最大容量
private int cap;
public LRUCache(int cap){
this.cap = cap;
map = new HashMap<>();
cache = new DoubleList();
}
public void put(int key,int value){
if (map.containsKey(key)){
// 删除旧数据
deleteKey(key);
addRecently(key,value);
return;
}
if (cache.size()==cap){
removeLeastRecently();
}
addRecently(key, value);
}
public int get(int key){
if (!map.containsKey(key)){
return -1;
}
makeRecently(key);
return map.get(key).val;
}
private void removeLeastRecently() {
Node first = cache.removeFirst();
map.remove(first.key);
}
private void deleteKey(int key) {
Node node = map.get(key);
map.remove(key);
cache.remove(node);
}
/* 将某个 key 提升为最近使用的 */
private void makeRecently(int key){
Node node = map.get(key);
cache.remove(node);
cache.addLast(node);
}
/* 添加最近使用的元素 */
private void addRecently(int key,int value){
Node node = new Node(key, value);
map.put(key,node);
cache.addLast(node);
}
}
class Node {
public int key, val;
public Node next, prev;
public Node(int k, int v) {
this.key = k;
this.val = v;
}
}
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;
}
// 在尾部添加节点,时间复杂度O(1)
public void addLast(Node x){
x.prev = tail.prev;
x.next = tail;
tail.prev.next = x;
tail.prev = x;
size++;
}
// 删除链表中的 x 节点(x 一定存在)
// 由于是双链表且给的是目标 Node 节点,时间 O(1)
public void remove(Node x){
x.prev.next = x.next;
x.next.prev = x.prev;
size--;
}
// 删除链表中第一个节点,并返回该节点,时间 O(1)
public Node removeFirst(){
if (head==tail){
return null;
}
Node first = head.next;
// head.next = head.next.next;
// head.next.prev = head;
remove(first);
return first;
}
public int size(){
return size;
}
}
用 Java 的内置类型 LinkedHashMap
class LRUCache {
int cap;
LinkedHashMap<Integer, Integer> cache = new LinkedHashMap<>();
public LRUCache(int capacity) {
this.cap = capacity;
}
public int get(int key) {
if (!cache.containsKey(key)) {
return -1;
}
// 将 key 变为最近使用
makeRecently(key);
return cache.get(key);
}
public void put(int key, int val) {
if (cache.containsKey(key)) {
// 修改 key 的值
cache.put(key, val);
// 将 key 变为最近使用
makeRecently(key);
return;
}
if (cache.size() >= this.cap) {
// 链表头部就是最久未使用的 key
int oldestKey = cache.keySet().iterator().next();
cache.remove(oldestKey);
}
// 将新的 key 添加链表尾部
cache.put(key, val);
}
private void makeRecently(int key) {
int val = cache.get(key);
// 删除 key,重新插入到队尾
cache.remove(key);
cache.put(key, val);
}
}
作者:静默虚空
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
2021-10-14 unity商店下载地址