Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get
and set
.
get(key)
- Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.set(key, value)
- Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.
Solution:
其实就是LinkedHashMap。我们可以用HashMap和双向链表来实现。最新取得和插入的数据移动到链表尾部。当容量满时,移除头部节点,并将头节点更新为下一个节点。
查询:
- 根据键值查询hashmap,若命中,则返回节点,否则返回null。
- 从双向链表中删除命中的节点,将其重新插入到表尾。
- 所有操作的复杂度均为O(1)。
插入:
- 将新的节点关联到Hashmap
- 如果Cache满了,删除双向链表的头节点,同时删除Hashmap对应的记录
- 将新的节点插入到双向链表尾部
public class LRUCache { private int capacity; private Map<Integer, CacheEntry> map; private CacheEntry head, tail; public static class CacheEntry { int key, data; CacheEntry prev, next; CacheEntry(int key, int data) { this.key = key; this.data = data; } } public LRUCache(int capacity) { this.capacity = capacity; this.map = new HashMap<Integer, CacheEntry>(capacity); } public int get(int key) { CacheEntry e = map.get(key); if(e == null) return -1; linkNodeLast(e); //将e节点移动到链表尾部 return e.data; } public void set(int key, int value) { CacheEntry e = map.get(key); if(e != null) { e.data = value; } else { e = new CacheEntry(key, value); map.put(key, e); } linkNodeLast(e); //将e节点移动到链表尾部 if(map.size() > capacity) { //移除头节点 CacheEntry oldHead = head; head = head.next; oldHead.next = null; head.prev = null; map.remove(oldHead.key); } } private void linkNodeLast(CacheEntry e) { if(e == tail) return; //如果要移动的节点就是尾节点,直接返回 if(tail == null) { //tail为null的话,说明目前还没有插入数据 head = e; //更新头节点 } else { if(head == e) { //如果等于头节点,需要把头节点移动到尾部,并更新头节点 head = head.next; } if(e.prev != null) { //如果e本身就是头节点的话,prev为null,所以要判断一下 e.prev.next = e.next; } if(e.next != null) { e.next.prev = e.prev; } tail.next = e; //将e节点放到链表尾部 e.prev = tail; e.next = null; } tail = e; //更新尾节点 } }
有个更简单的方法,head和tail不保存实际内容,仅仅代表头部和尾部,这样可以避免上个方法中移动头部和尾部节点判断null的问题。
public class LRUCache { private int capacity; private Node head, tail; private Map<Integer, Node> map = new HashMap<>(); public static class Node { int key, value; Node prev, next; public Node(int k, int v) { key = k; value = v; } } public LRUCache(int capacity) { this.capacity = capacity; head = new Node(0, 0); tail = new Node(0, 0); head.next = tail; tail.prev = head; } public int get(int key) { Node node = map.get(key); if(node == null) return -1; linkNodeLast(node); return node.value; } public void set(int key, int value) { Node node = map.get(key); if(node == null) { node = new Node(key, value); } else { node.value = value; } map.put(key, node); linkNodeLast(node); if(map.size() > capacity) { Node item = head.next; head.next = item.next; item.next.prev = head; map.remove(item.key); } } private void linkNodeLast(Node node) { if(node.prev != null) { node.prev.next = node.next; node.next.prev = node.prev; } node.prev = tail.prev; tail.prev.next = node; node.next = tail; tail.prev = node; } }
相关推荐
Leetcode-LRU-cache LRU缓存 设计和实现最近最少使用 (LRU) 缓存的数据结构。 它应该支持以下操作:get 和 put。 get(key) - 如果键存在于缓存中,则获取键的值(将始终为正),否则返回 -1。 put(key, value) - ...
lru缓存leetcode 问题描述 设计一个遵循最近最少使用 (LRU) 缓存约束的数据结构。 实现 LRUCache 类: LRUCache(int capacity)使用正大小容量初始化 LRU 缓存。 int get(int key)如果键存在则返回键的值,否则返回-1...
@lru_cache(None) 使用动态规划避免重复工作 2020 年 1 月 6 日 合并两个排序列表 / 可以使用递归实现 通过使用指针也可以具有 O(1) 复杂度 2020 年 1 月 7 日 类似做法 斐波那契数 爬楼梯 有效括号 快乐号/ 2020 年...
lru-cache-0146 动态规划 爬楼梯-0070 coin-change-0322 coin-change-ii-0518 组合和-iv-0377 解码方式-0091 盗家贼-0198 盗家贼-ii-0213 jump-game-0055 最长公共子序列1143 最长公共子串 最长递增子序列0300 最大...
lru cache leetcode LeetCode-Tencent50 Task0 最小栈 Task1 有效的括号 Task2 数组中的第K个最大元素 Task3 合并K个有序链表 Task4 买卖股票的最佳时机 II Task5 排序链表 Task6 子集 Task7 只出现一次的数字 Task8...
LRU_cache (Leetcode 146) 设计和实现最近最少使用 (LRU) 缓存的数据结构。 它应该支持以下操作:get 和 set。 get(key) – 如果键存在于缓存中,则获取键的值(将始终为正),否则返回 -1。 set(key, value) – ...
lru cache leetcode Leetcode Solution 1. Two Sum 二重循环遍历 2. Add Two Numbers 链表求和,哨兵节点 3. Longest Substring Without Repeating Characters 最长没有重复字符的子序列 记录各字符最近一次出现的...
lru cache leetcode LeetCode-go leetcode中文网站 目录 序号 名字 中文名字 备注 0 binarySearch 二分查找法 1 两数之和 2 两数相加 3 longestSubstr 无重复最长字串 4 findMedianSortedArrays 寻找两个有序数组的...
对应的代码文件为lru-cache.cpp About This Repo 所有代码均为原创,可随意转载、使用、修改,请标明出处。 代码不追求最短,但追求逻辑上清楚,易于重复。 不采用太偏门的方法,保证代码易读、易理解。 如果你有不...
lru缓存leetcode Leetcode-练习-GHC19 最初是作为关于代码实践的 whatsapp 研究小组更新的存储库 - 用于 Grace Hopper ...Cache-3 次 力码 361 力码 463 二叉搜索树到排序数组。 截留雨水。 整数到罗
lru缓存leetcode LRU缓存 受启发的简单 LRU 缓存实现 发展 建造 ./gradlew build 测试 ./gradlew test 使用示例 LRUCache< String , String > cache = new LRUCache<> ( 2 /* capacity */ ); cache . put( " ...
lru缓存leetcode LRU_Cache LRU_Cache 是一个 leetcode 问题,需要深入了解数据结构。 在 LRU_Cache 的实现中,使用了 LinkedHashTable。
lru缓存leetcode LRU_Cache 灵感来自 LeetCode OJ:
lru缓存leetcode leetcode-cs 带有单元测试的 C# 提交。 强调 简单的 HashSet , IEnumerable.Count() string.Substring() , string.Concat() Array.Sort() , hat operator (^) HashSet Stack , IEnumerable....
lru缓存leetcode 问题描述 设计和实现最不常用 (LFU) 缓存的数据结构。 实现 LFUCache 类: LFUCache(int capacity)用数据结构的容量初始化对象。 int get(int key)如果键存在于缓存中,则获取int get(int key)的值...
lru cache leetcode LRU Cache Algorithm ...cache-lines and track the "Least Recently Used" cache-line based on age-bits. In such an implementation, every time a cache-line is used, the
LRU-Cache 键值对的 LRU 缓存实现。 Leetcode #146。 使用简单的 int32 数据类型的 LRU 缓存实现。 复杂度 O(1)。 空间 O(N)。 数据结构:双链表头尾节点,加上哈希查找表。 对双链表使用抽象。
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. get(key) – Get the value (will always be positive) of the key if ...
leetcode 《算法面试通关 40 讲》挑战 数组、链表 Easy Easy Medium Medium Hard 堆栈、队列 Easy Easy Easy 优先队列 Easy Hard 哈希表 Easy Easy Medium Medium 树、二叉树、二叉搜索树 Medium Easy Medium 递归、...