[leetcode]146. LRU CacheLRU缓存
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 the key exists in the cache, otherwise return -1.put(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.
Follow up:
Could you do both operations in O(1) time complexity?
题意:实现一个LRU缓存
Solution: HashMap + doubly LinkedList
删除操作分为2种情况:
- 给定node data删除node: 单链表和双向链表都需要从头到尾进行遍历从而找到对应node进行删除,时间复杂度都为O(n)。
- 给定node address删除node: 单链表需要从头到尾遍历直到找到该node的pre node,时间复杂度为O(n)。双向链表只需O(1)时间即能找到该node的pre node。
HashMap保存node address,可以基本保证在O(1)时间内找到该node
具体实现如下:
put(1,1): 先create 一个newNode(1,1)地址为$Node@435,HashMap存入(1, $Node@435), 双向链表将newNode(1,1)设为head

put(2,2): 先create 一个newNode(2,2)地址为$Node@436,HashMap存入(2, $Node@436), 双向链表将newNode(2,2)设为head

get(1): 先在HashMap中找到1对应node的地址$Node@435,通过该地址找到双向链表对应node(1,1) 。删除该node(1,1)再重新setHead


put(3,3): 先create 一个newNode(3,3)地址为$Node@437, 发现Cache is full! We need to evict something to make room.
1. 首先释放HashMap空间,通过双向链表中tailNode的key找到要在HashMap中删除的key

2. 然后删掉双向链表的tailNode

3. 将newNode(3,3)在双向链表中setHead

思考:
1. why not using java.util.LinkedinList?
因为java自带的linkedlist中,删除操作是从头到尾scan特定值再删除,时间为O(n)。但题目要求O(1)。
2. why not using java.util.LinkedHashMap?
这题说白了,就是考察java自带的LinkedHashMap是怎么实现的,我们当然不能。
code
public class LRUCache {
private int capacity;
private final HashMap<Integer, Node> map;
private Node head;
private Node tail;
public LRUCache(int capacity) {
this.capacity = capacity;
map = new HashMap<>();
}
public int get(int key) {
// no key exists
if (!map.containsKey(key)) return -1;
// key exists, move it to the front
Node n = map.get(key);
remove(n);
setHead(n);
return n.value;
}
public void put(int key, int value) {
// key exits
if (map.containsKey(key)) {
// update the value
Node old = map.get(key);
old.value = value;
// move it to the front
remove(old);
setHead(old);
}
// no key exists
else {
Node created = new Node(key, value);
// reach the capacity, move the oldest item
if (map.size() >= capacity) {
map.remove(tail.key);
remove(tail);
setHead(created);
}
// insert the entry into list and update mapping
else {
setHead(created);
}
map.put(key, created);
}
}
private void remove(Node n) {
if (n.prev != null) {
n.prev.next = n.next;
} else {
head = n.next;
}
if (n.next != null) {
n.next.prev = n.prev;
} else {
tail = n.prev;
}
}
private void setHead(Node n) {
n.next = head;
n.prev = null;
if (head != null) head.prev = n;
head = n;
if (tail == null) tail = head;
}
// doubly linked list
class Node {
int key;
int value;
Node prev;
Node next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
}
[leetcode]146. LRU CacheLRU缓存的更多相关文章
- Java实现 LeetCode 146 LRU缓存机制
146. LRU缓存机制 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - ...
- leetcode 146. LRU Cache 、460. LFU Cache
LRU算法是首先淘汰最长时间未被使用的页面,而LFU是先淘汰一定时间内被访问次数最少的页面,如果存在使用频度相同的多个项目,则移除最近最少使用(Least Recently Used)的项目. LFU ...
- [LeetCode] 146. LRU Cache 最近最少使用页面置换缓存器
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- [Leetcode]146.LRU缓存机制
Leetcode难题,题目为: 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key ...
- [LeetCode] 146. LRU Cache 近期最少使用缓存
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- LeetCode 146. LRU缓存机制(LRU Cache)
题目描述 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (k ...
- Leetcode 146. LRU 缓存机制
前言 缓存是一种提高数据读取性能的技术,在计算机中cpu和主内存之间读取数据存在差异,CPU和主内存之间有CPU缓存,而且在内存和硬盘有内存缓存.当主存容量远大于CPU缓存,或磁盘容量远大于主存时,哪 ...
- Java for LeetCode 146 LRU Cache 【HARD】
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- leetcode@ [146] LRU Cache (TreeMap)
https://leetcode.com/problems/lru-cache/ Design and implement a data structure for Least Recently Us ...
随机推荐
- javascript创建对象之稳妥构造函数模式(七)
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象.稳妥对象最适合在一些安全的环境中(禁止使用this和new)或者在防止数据被其他应用程序改动时. 稳妥构造函数模式有2个特点:1.新 ...
- Solr优化案例分析
随着umc接入主机的数量越来越多,每天产生的syslog日志数量也在剧增, 之前一天产生的syslog数量才不 到1W,随着整个集团的网络设备不端接入,导致现在每天产生的syslog数量大概在180w ...
- 内置锁(三)synchronized的几个要注意的对象监视器
前言 经过前面的两篇文章的介绍,可以清楚知道,synchronized可以用于修饰一个方法 或者 代码块,线程要访问这些临界区代码,则要先获取对应的 对象监视器 ,从而使多个线程互斥访问临界区. ...
- Pillow 读取图片截断错误
做图像处理的时候,Pillow是经常使用到的模块. 最近在读取图片的时候出现了一个错误. OSError: image file is truncated (461 bytes not process ...
- 网站搜索引擎优化SEO策略及相关工具资源
网站优化的十大奇招妙技 1. 选择有效的关键字: 关键字是描述你的产品及服务的词语,选择适当的关键字是建立一个高排名网站的第一步.选择关键字的一个重要的技巧是选取那些常为人们在搜索时所用到的关键字. ...
- OpenCL 归约 1
▶ 照着书上的代码,写了几个一步归约的计算,只计算一步,将原数组归约到不超过 1024 个工作项 ● 代码 // kernel.cl __kernel void reduce01(__global u ...
- 34. CentOS-6.3安装配置Apache2.2.6
安装说明 安装环境:CentOS-6.3安装方式:源码编译安装 软件:httpd-2.2.6.tar.gz | pcre-8.32.tar.gz | apr-1.4.6.tar.gz | apr-u ...
- IOUtils总结
参考:https://www.cnblogs.com/xing901022/p/5978989.html 常用的静态变量 在IOUtils中还是有很多常用的一些变量的,比如换行符等等 public s ...
- leetcode953
public class Solution { public bool IsAlienSorted(string[] words, string order) { string HumanDic = ...
- bootstrap做的导航
顶部导航:nav-tabs 左边导航:nav-list 响应式布局:div嵌套 ~ container.row.ol-lg-X 效果: 源码: <!DOCTYPE html> <ht ...