Q200510-03-03 :LRU缓存机制
LRU缓存机制
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?
示例:
LRUCache cache = new LRUCache( 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
代码:
package test3; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; class Node { int key; int val; Node next; Node prev; public Node(int key, int val){ this.key = key; this.val = val; next = null; prev = null; } } public class LruCache { private int capacity; private HashMap<Integer, Node> cacheMap; private Node head, tail; public LruCache(int capacity) { this.capacity = capacity; this.cacheMap = new LinkedHashMap<>(); this.head = new Node(-1, -1); this.tail = new Node(-1, -1); head.next = tail; head.prev = tail; tail.next = head; tail.prev = head; } public int get(int key) { if(!cacheMap.containsKey(key)) { return -1; } Node node = cacheMap.get(key); moveToHead(node); return node.val; } public void put(int key, int value) { if (cacheMap.containsKey(key)) { cacheMap.get(key).val = value; moveToHead(cacheMap.get(key)); } else { Node node = new Node(key, value); if (cacheMap.size() >= this.capacity) { Node rm = tail.prev; deleteNode(rm); cacheMap.remove(rm.key); } insertHead(node); cacheMap.put(key, node); } } private void moveToHead(Node node) { deleteNode(node); insertHead(node); } private void insertHead(Node node) { Node next = head.next; head.next = node; node.prev = head; node.next = next; next.prev = node; } private void deleteNode(Node node) { Node front = node.prev; Node end = node.next; front.next = end; end.prev = front; } public void printCache() { StringBuilder sb=new StringBuilder(); sb.append("["); List<String> ls=new ArrayList<String>(); for(int key:cacheMap.keySet()) { Node value=cacheMap.get(key); ls.add("("+key+","+value.val+")"); } sb.append(String.join(",", ls)); sb.append("]"); System.out.println(sb.toString()); } public static void main(String[] args) throws Exception{ LruCache cache=new LruCache(2); cache.put(1,1); System.out.print("....."); cache.printCache(); System.out.println(); cache.put(2,2); System.out.print("....."); cache.printCache(); System.out.println(); System.out.print(cache.get(1)); System.out.print("....."); cache.printCache(); System.out.println(); cache.put(3, 3); System.out.print("....."); cache.printCache(); System.out.println(); System.out.print(cache.get(2)); System.out.print("....."); cache.printCache(); System.out.println(); cache.put(4, 4); System.out.print("....."); cache.printCache(); System.out.println(); System.out.print(cache.get(1)); System.out.print("....."); cache.printCache(); System.out.println(); System.out.print(cache.get(3)); System.out.print("....."); cache.printCache(); System.out.println(); System.out.print(cache.get(4)); System.out.print("....."); cache.printCache(); System.out.println(); } }
输出:
.....[(1,1)] .....[(1,1),(2,2)] 1.....[(1,1),(2,2)] .....[(1,1),(3,3)] -1.....[(1,1),(3,3)] .....[(3,3),(4,4)] -1.....[(3,3),(4,4)] 3.....[(3,3),(4,4)] 4.....[(3,3),(4,4)]
--2020年5月11日--
分类:
Java.Algorithm
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)