14.LRU缓存
题目描述
请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
实现 LRUCache 类:
LRUCache(int capacity):以正整数作为容量capacity初始化LRU缓存
int get(int key):如果关键字key存在于缓存中,则返回关键字的值,否则返回-1。
void put(int key, int value):如果关键字key已经存在,则变更其数据值value;如果不存在,则向缓存中插入该组key-value。如果插入操作导致关键字数量超过capacity,则应该逐出最久未使用的关键字。
题目链接
https://leetcode-cn.com/problems/lru-cache/
题目说明
函数get和put必须以O(1)的平均时间复杂度运行。
复杂度分析
时间复杂度:对于put和get都是O(1)。
空间复杂度:O(capacity),因为哈希表和双向链表最多存储capacity+1个元素。
样例描述
输入 ["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"] [[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]] 输出 [null, null, null, 1, null, -1, null, -1, 3, 4] 解释 LRUCache lRUCache = new LRUCache(2); lRUCache.put(1, 1); // 缓存是 {1=1} lRUCache.put(2, 2); // 缓存是 {1=1, 2=2} lRUCache.get(1); // 返回 1 lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3} lRUCache.get(2); // 返回 -1 (未找到) lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3} lRUCache.get(1); // 返回 -1 (未找到) lRUCache.get(3); // 返回 3 lRUCache.get(4); // 返回 4
代码
class LRUCache { class DListNode { int value; int key; DListNode prev; DListNode next; public DListNode() {} public DListNode(int _key, int _value) { value = _value; key = _key; } } private Map<Integer, DListNode> cache = new HashMap<Integer, DListNode>(); private int size; private int capacity; private DListNode head, tail; public LRUCache(int capacity) { this.capacity = capacity; head = new DListNode(); tail = new DListNode(); head.next = tail; tail.prev = head; } public int get(int key) { DListNode node = cache.get(key); if (node == null) { return -1; } // 因为是LRU算法,获取过的key,会放到头部 moveToHead(node); return node.value; } public void put(int key, int value) { DListNode node = cache.get(key); if (node == null) { DListNode newNode = new DListNode(key, value); cache.put(key, newNode); ++size; addToHead(newNode); if (size > capacity) { DListNode res = removeToTail(); cache.remove(res.key); --size; } } else { node.value = value; moveToHead(node); } } public void removeNode(DListNode node) { node.prev.next = node.next; node.next.prev = node.prev; } public void addToHead(DListNode node) { node.next = head.next; node.next.prev = node; head.next = node; node.prev = head; } public void moveToHead(DListNode node) { // 先将其移除 removeNode(node); // 再将其插入到头部 addToHead(node); } public DListNode removeToTail() { DListNode res = tail.prev; removeNode(res); return res; } } /** * Your LRUCache object will be instantiated and called as such: * LRUCache obj = new LRUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */
本文来自博客园,作者:jsqup,转载请注明原文链接:https://www.cnblogs.com/jsqup/p/15835507.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?