LRU Cache 题解
题意
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.
这道题的题意就是说,使用LRU Cache,就是将最新使用的放置在前面,以便下次取的时候方便,其余则依次往下移动;
思路
其实我也是根据别人的想法做的,用链表加入值,因为链表对于往前往后添加或者删除都非常方便,但是有个麻烦的地方在于,我并不知知道他的位置在哪里,只能循环去找,因此我使用了一个哈希数组进行存储她的key和下标;
实现
我的实现(比较白痴)
struct Node {
int key;
int value;
Node(int _k, int _v) {key = _k; value = _v;}
};
class LRUCache{
public:
unordered_map<int, int> maps;
list<Node> lists;
int size;
LRUCache(int capacity) {
size = capacity;
}
/**
* 获取值,同时获取也算是一种访问
*
* @param key <#key description#>
*
* @return <#return value description#>
*/
int get(int key) {
if (maps.size() == 0) {
return -1;
}
if (maps.find(key) != maps.end()) {
auto key_value = maps.find(key);
int j = 0;
for (auto itr = lists.begin(); itr != lists.end() && j < lists.size(); itr++, j++) {
if (j == key_value->second) {
int value = (*itr).value;
lists.push_front(Node((*itr).key, (*itr).value));
// 更新lists和maps
lists.erase(itr);
// 将要更新的迭代器之前的下标都要加上1,其余的位置不需要改变
for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
if (mitr->second < key_value->second){
mitr->second++;
}
}
// 更新全部位置
key_value->second = 0;
return value;
}
}
}
return -1;
}
/**
* 添加新值,不过需要注意的是当内存不够的情况下,需要删除掉最不经常使用的
*
* @param key <#key description#>
* @param value <#value description#>
*/
void set(int key, int value) {
if (lists.size() == size) {
// 满了先进行删除
list<Node>::iterator lend = --lists.end();
lists.pop_back();
int lkey = lend->key;
maps.erase(maps.find(lkey));
lists.push_front(Node(key, value));
for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
mitr->second++;
}
maps.insert(make_pair(key, 0));
}
else {
// 存在的话
if (maps.find(key) != maps.end()) {
auto key_value = maps.find(key);
maps[key] = 0;
for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
if (mitr->second < key_value->second){
mitr->second++;
}
}
// 更新全部位置
key_value->second = 0;
}
else {
lists.push_front(Node(key, value));
for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
mitr->second++;
}
maps.insert(make_pair(key, 0));
}
}
}
};
int main(int argc, const char * argv[]) {
// insert code here...
LRUCache cache(5);
cache.set(1, 10);
cache.set(2, 20);
cache.set(3, 30);
//cout << "cache..." << cache.get(2) << endl;
cache.set(4, 40);
cache.set(5, 50);
cache.set(8, 80);
//cout << "cache..." << cache.get(1) << endl;
cout << "cache..." << cache.get(5) << endl;
return 0;
}
如上面所说,我需要不停的去更新其的位置,这样才能根据正确的位置去获取到具体的结点信息;根据题目的要求,需要控制时间复杂度在1,所以需要需要一个哈希数组去记录其位置;但是我好像并没有做到,依旧使用了一个循环。。。
我的基础上优化
struct node{
int key;
int value;
node(int k, int v):key(k), value(v){}
};
/*
* 注意整体思路是,使用双向list每次set或get一个元素时都把这个元素放到list的头部,无需统计每个元素的操作次数,实际上LRU的意思
* 就是根据元素最后被访问的时间来决定替换哪个,故list中尾部元素即被替换.
* STL技巧:1、使用map的find方法来判断key是否已经存在,返回值和map的end迭代器比较;
2、使用unordered_map,它是hash_map,存取时间都是O(1),用它存储元素的position迭代器,是为了方便splice函数调用
* list.splice(position, list, element_pos)函数作用是把list的element_pos处的元素插入到position位置,本题中
为了移动元素到list头部
*/
class LRUCache{
int size;
list<node> values;
unordered_map<int, list<node>::iterator> positions;
public:
LRUCache(int capacity) {
size = capacity;
}
int get(int key) {
if(positions.find(key) != positions.end()){
values.splice(values.begin(), values, positions[key]);
positions[key] = values.begin();
return values.begin()->value;
}
return -1;
}
void set(int key, int value) {
if(positions.find(key) != positions.end()){
values.splice(values.begin(), values, positions[key]); //移动被访问元素到头部
values.begin()->value = value;
positions[key] = values.begin(); //更新其位置,注意此处的position只是一个指针,当此key在list中被挤到其他位置后,positions里保存的位置也会跟着变化,因为它仅仅是一个指向该结点的指针
}
else if(values.size()<size){
values.push_front(node(key, value));
positions[key] = values.begin();
}
else{
node last = values.back();
values.pop_back();
positions.erase(last.key);
values.push_front(node(key, value));
positions[key] = values.begin();
}
}
};
将我的int下标,改成了纪录链表的迭代器,这下使用了splice会很方便,同时控制了时间复杂度。
总结
并没有。
LRU Cache 题解的更多相关文章
- LeetCode题解: LRU Cache 缓存设计
LeetCode题解: LRU Cache 缓存设计 2014年12月10日 08:54:16 邴越 阅读数 1101更多 分类专栏: LeetCode 版权声明:本文为博主原创文章,遵循CC 4 ...
- 146. LRU Cache
题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...
- LeetCode解题报告:LRU Cache
LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should suppo ...
- LRU Cache leetcode java
题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...
- 【leetcode刷题笔记】LRU Cache
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- [LeetCode] LRU Cache 最近最少使用页面置换缓存器
Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...
- 【leetcode】LRU Cache
题目简述: Design and implement a data structure for Least Recently Used (LRU) cache. It should support t ...
- LeetCode:LRU Cache
题目大意:设计一个用于LRU cache算法的数据结构. 题目链接.关于LRU的基本知识可参考here 分析:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::l ...
- LRU Cache实现
最近在看Leveldb源码,里面用到LRU(Least Recently Used)缓存,所以自己动手来实现一下.LRU Cache通常实现方式为Hash Map + Double Linked Li ...
随机推荐
- android 多个shortCut快捷方式实现以及对58同城快捷方式的实现思路的研究
这几天,项目中有个新需求,需要按照模块添加不同的快捷方式到桌面上,从而方便用户的使用.特意进行了研究并分析了下58上面桌面快捷方式的实现. 首先多个shortcut的实现: <activity ...
- php 连接 mssql sql2008
摘要 sql server 2008 1.下载微软提供的dll 下载地址:http://www.microsoft.com/en-us/download/details.aspx?id=20098 p ...
- 表达式语言--在MVC中应用表达式语言
之前讲解的MVC设计模式中一直有DAO存在,而且所有的对象都保存在VO之中,那么这时如果将一个VO传递到JSP文件中,那么JSP需要导入VO包,如果使用表达式语言的话,导入VO包就没有任何意义了. V ...
- Installation error: INSTALL_FAILED_UID_CHANGED 的解决办法
出现此问题的原因大多是apk冲突造成,解决的办法如下: 1. Settings -> Applications, 卸载出现问题的apk,重新安装即可. 2. 如果apk无法卸载,则将apk相关 ...
- mysql导出表结构
在命令行下mysql的数据导出有个很好用命令mysqldump,它的参数有一大把,可以这样查看: mysqldump 最常用的: mysqldump -uroot -pmysql databasefo ...
- oracle数据库兼容mysql的差异写法
1.sysdate改为sysdate(),或者now(); 2.nvl(expr1,expr2) 改为IFNULL(expr1,expr2) nvl2(expr1,expr2,expr3)改为 IF( ...
- ms10_046_shortcut_icon_dllloader漏洞利用和ettercap dns欺骗
ms10_046_shortcut_icon_dllloader漏洞利用过程 msf > use exploit/windows/browser/ms10_046_shortcut_icon_d ...
- 2015 HDU 计算机学院 院赛 1003 玩骰子
Problem Description Nias与Ains都特别喜欢玩骰子,而且都自以为比对方玩得更溜. 终于有一天,他们决定用骰子来一决高下! 一般的骰子玩法已经不足以体现他们的水平了,于是 ...
- 同花顺核新下单程序的"界面不操作超时时间"的设定
"界面不操作超时时间"的设定 同花顺核新下单程序的'界面不操作超时时间'的设定 系统> 系统设置> 界面设置> 界面不操作超时时间(分): 在这个输入框里填上个3 ...
- urllib2修改header
python网络访问的标准模块 urllib与urllib2并不是升级版的关系,具体可见谷歌文章:difference between urllib and urllib2urllib2的官方文档:h ...