[LeetCode] LRU Cache 最近最少使用页面置换缓存器
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?
Example:
LRUCache cache = new LRUCache( 2 /* capacity */ ); cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4
这道题让我们实现一个 LRU 缓存器,LRU 是 Least Recently Used 的简写,就是最近最少使用的意思。那么这个缓存器主要有两个成员函数,get 和 put,其中 get 函数是通过输入 key 来获得 value,如果成功获得后,这对 (key, value) 升至缓存器中最常用的位置(顶部),如果 key 不存在,则返回 -1。而 put 函数是插入一对新的 (key, value),如果原缓存器中有该 key,则需要先删除掉原有的,将新的插入到缓存器的顶部。如果不存在,则直接插入到顶部。若加入新的值后缓存器超过了容量,则需要删掉一个最不常用的值,也就是底部的值。具体实现时我们需要三个私有变量,cap, l和m,其中 cap 是缓存器的容量大小,l是保存缓存器内容的列表,m是 HashMap,保存关键值 key 和缓存器各项的迭代器之间映射,方便我们以 O(1) 的时间内找到目标项。
然后我们再来看 get 和 put 如何实现,get 相对简单些,我们在 HashMap 中查找给定的 key,若不存在直接返回 -1。如果存在则将此项移到顶部,这里我们使用 C++ STL 中的函数 splice,专门移动链表中的一个或若干个结点到某个特定的位置,这里我们就只移动 key 对应的迭代器到列表的开头,然后返回 value。这里再解释一下为啥 HashMap 不用更新,因为 HashMap 的建立的是关键值 key 和缓存列表中的迭代器之间的映射,get 函数是查询函数,如果关键值 key 不在 HashMap,那么不需要更新。如果在,我们需要更新的是该 key-value 键值对儿对在缓存列表中的位置,而 HashMap 中还是这个 key 跟键值对儿的迭代器之间的映射,并不需要更新什么。
对于 put,我们也是现在 HashMap 中查找给定的 key,如果存在就删掉原有项,并在顶部插入新来项,然后判断是否溢出,若溢出则删掉底部项(最不常用项)。代码如下:
class LRUCache{
public:
LRUCache(int capacity) {
cap = capacity;
} int get(int key) {
auto it = m.find(key);
if (it == m.end()) return -;
l.splice(l.begin(), l, it->second);
return it->second->second;
} void put(int key, int value) {
auto it = m.find(key);
if (it != m.end()) l.erase(it->second);
l.push_front(make_pair(key, value));
m[key] = l.begin();
if (m.size() > cap) {
int k = l.rbegin()->first;
l.pop_back();
m.erase(k);
}
} private:
int cap;
list<pair<int, int>> l;
unordered_map<int, list<pair<int, int>>::iterator> m;
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/146
类似题目:
Design Compressed String Iterator
参考资料:
https://leetcode.com/problems/lru-cache/
http://www.cnblogs.com/TenosDoIt/p/3417157.html
https://leetcode.com/problems/lru-cache/discuss/46285/unordered_map-list
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] LRU Cache 最近最少使用页面置换缓存器的更多相关文章
- [LeetCode] 146. LRU Cache 最近最少使用页面置换缓存器
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- 146 LRU Cache 最近最少使用页面置换算法
设计和实现一个 LRU(最近最少使用)缓存 数据结构,使它应该支持以下操作: get 和 put .get(key) - 如果密钥存在于缓存中,则获取密钥的值(总是正数),否则返回 -1.put(k ...
- [LeetCode] LFU Cache 最近最不常用页面置换缓存器
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...
- [LeetCode] 460. LFU Cache 最近最不常用页面置换缓存器
Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the f ...
- LeetCode之LRU Cache 最近最少使用算法 缓存设计
设计并实现最近最久未使用(Least Recently Used)缓存. 题目描述: Design and implement a data structure for Least Recently ...
- LeetCode——LRU Cache
Description: Design and implement a data structure for Least Recently Used (LRU) cache. It should su ...
- [LeetCode]LRU Cache有个问题,求大神解答【已解决】
题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...
- LeetCode:LRU Cache
题目大意:设计一个用于LRU cache算法的数据结构. 题目链接.关于LRU的基本知识可参考here 分析:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::l ...
- LeetCode: LRU Cache [146]
[题目] Design and implement a data structure for Least Recently Used (LRU) cache. It should support th ...
随机推荐
- javascript的变量作用域--对比js、php和c的for循环
为什么要写这篇文章呢?主要是给自己提个醒,js的水很深,需要小心点儿才能趟过去,更何况自己不是专业人士,那就得更加小心了. 看下面的js代码: <!DOCTYPE html> <ht ...
- ASP.NET Core 中文文档 第三章 原理(15)请求功能
作者:Steve Smith 翻译:谢炀(kiler398) 校对:姚阿勇(Dr.Yao).孟帅洋(书缘) 涉及到如何处理 HTTP 请求以及响应的独立 Web 服务器功能已经被分解成独立的接口,这些 ...
- MyCat源码分析系列之——前后端验证
更多MyCat源码分析,请戳MyCat源码分析系列 MyCat前端验证 MyCat的前端验证指的是应用连接MyCat时进行的用户验证过程,如使用MySQL客户端时,$ mysql -uroot -pr ...
- javascript性能优化:创建javascript无阻塞脚本
javaScript 在浏览器中的运行性能,在web2.0时代显得尤为重要,成千上万行javaScript代码无疑会成为性能杀手, 在较低版本的浏览器执行JavaScript代码的时候,由于浏览器只使 ...
- 【IOS开发笔记03-视图相关】简单计算器的实现
UIView 经过前几天的快速学习,我们初步了解的IOS开发的一些知识,中间因为拉的太急,忽略了很多基础知识点,这些知识点单独拿出来学习太过枯燥,我们在今后的项目中再逐步补齐,今天我们来学习APP视图 ...
- 地图中插入表格——ArcMap篇
在制作专题图的过程中,不但要有地理要素表示空间位置,经常还要在图的周围制作一些表格数据.这里对ArcMap中的插入方法进行总结. 方法一:插入对象 利用菜单中的"插入"-" ...
- 北京54全国80及WGS84坐标系的相互转换
这三个坐标系统是当前国内较为常用的,它们均采用不同的椭球基准.其中北京54坐标系,属三心坐标系,大地原点在苏联的普而科沃,长轴6378245m,短轴6356863,扁率1/298.3:西安80坐标系, ...
- Android简单介绍SharedPreference,内部文件,sdcard数据存储
SharedPreference 以xml的结构储存简单的数据,储存在data/data/程序包名/shared_prefs文件夹中 使用方式 创建对象的方式有三种 Context 的 getShar ...
- unable to boot the simulator,无法启动模拟器已解决
突然模拟器报错:unable to boot the simulator(无法启动模拟器) 试了好几种解决办法,删除所有的模拟器重启以后再添加,删除钥匙串登陆中的证书,重新安装Xcode都不行 最后通 ...
- UITableview delegate dataSource调用探究
UITableview是大家常用的UIKit组件之一,使用中我们最常遇到的就是对delegate和dataSource这两个委托的使用.我们大多数人可能知道当reloadData这个方法被调用时,de ...