[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 ...
随机推荐
- OSPF两种组播地址的区别和联系
1.点到点网络: 是连接单独的一对路由器的网络,点到点网络上的有效邻居总是可以形成邻接关系的,在这种网络上,OSPF包的目标地址使用的是224.0.0.52.广播型网络, 比如以太网,Token Ri ...
- Fragment之介绍(转)
http://www.cnblogs.com/plokmju/p/3239265.html 前言 开门见山开篇名义,本篇博客将讲解一下Android中Fragment的内容,必要的地方会提供相应的演示 ...
- 【Codeforces】CF 2 B The least round way(dp)
题目 传送门:QWQ 分析 求结尾0的数量QwQ. 10只能是$ 2 \times 5 $,我们预处理出每个数因子中2和5的数量. 我们接着dp出从左上到右下的经过的最少的2的数量和最少的5的数量.两 ...
- 在ubuntu中如何向U盘复制粘贴文件 Read-only file system
1. 重新挂载被操作分区的读写权限,如U盘 $ sudo mount -o remount,rw /media/lenmom/00093FA700017B96 #U盘挂载目录,如果是系统中的其他盘, ...
- nginx经过多层代理后获取真实来源ip
nginx取 $remote_addr 当做真实ip,而事实上,$http_X_Forwarded_For 才是用户真实ip,$remote_addr只是代理上一层的地址 解决方案: 在 http 模 ...
- 软件测试——Peer Review(简介)
1. 同行评审的种类和对象 同行评审活动的关注点应该是工作产品中的缺陷,而不应该是工作产品的作者或者生产者,管理者也不应使用同行评审的结果去评价个人的行为. 同行评审的分类有很多种,自从IBM的Fag ...
- Axure8.1.0.3372 注册码
Axure8.1.0.3372 注册码 转载:http://blog.csdn.net/cslucifer/article/details/79355007 Koshy wTADPqxn3KChzJx ...
- TDictionary 是delphi用的,c++builder用起来太吃力。
TDictionary 是delphi用的,c++builder用起来太吃力.c++还是用std::map代替.c++d map很好用啊.https://blog.csdn.net/ddkxddkx/ ...
- 前端-CSS-7-标准文档流&行内元素和块级元素转换
1.什么是标准文档流 <!-- 什么是标准文档流 宏观的将,我们的web页面和ps等设计软件有本质的区别 web 网页的制作 是个“流” 从上而下 ,像 “织毛衣” 而设计软件 ,想往哪里画东 ...
- ABAP-长文本处理