题意

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和下标;

实现

我的实现(比较白痴)

  1. struct Node {
  2. int key;
  3. int value;
  4. Node(int _k, int _v) {key = _k; value = _v;}
  5. };
  6. class LRUCache{
  7. public:
  8. unordered_map<int, int> maps;
  9. list<Node> lists;
  10. int size;
  11. LRUCache(int capacity) {
  12. size = capacity;
  13. }
  14. /**
  15. * 获取值,同时获取也算是一种访问
  16. *
  17. * @param key <#key description#>
  18. *
  19. * @return <#return value description#>
  20. */
  21. int get(int key) {
  22. if (maps.size() == 0) {
  23. return -1;
  24. }
  25. if (maps.find(key) != maps.end()) {
  26. auto key_value = maps.find(key);
  27. int j = 0;
  28. for (auto itr = lists.begin(); itr != lists.end() && j < lists.size(); itr++, j++) {
  29. if (j == key_value->second) {
  30. int value = (*itr).value;
  31. lists.push_front(Node((*itr).key, (*itr).value));
  32. // 更新lists和maps
  33. lists.erase(itr);
  34. // 将要更新的迭代器之前的下标都要加上1,其余的位置不需要改变
  35. for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
  36. if (mitr->second < key_value->second){
  37. mitr->second++;
  38. }
  39. }
  40. // 更新全部位置
  41. key_value->second = 0;
  42. return value;
  43. }
  44. }
  45. }
  46. return -1;
  47. }
  48. /**
  49. * 添加新值,不过需要注意的是当内存不够的情况下,需要删除掉最不经常使用的
  50. *
  51. * @param key <#key description#>
  52. * @param value <#value description#>
  53. */
  54. void set(int key, int value) {
  55. if (lists.size() == size) {
  56. // 满了先进行删除
  57. list<Node>::iterator lend = --lists.end();
  58. lists.pop_back();
  59. int lkey = lend->key;
  60. maps.erase(maps.find(lkey));
  61. lists.push_front(Node(key, value));
  62. for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
  63. mitr->second++;
  64. }
  65. maps.insert(make_pair(key, 0));
  66. }
  67. else {
  68. // 存在的话
  69. if (maps.find(key) != maps.end()) {
  70. auto key_value = maps.find(key);
  71. maps[key] = 0;
  72. for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
  73. if (mitr->second < key_value->second){
  74. mitr->second++;
  75. }
  76. }
  77. // 更新全部位置
  78. key_value->second = 0;
  79. }
  80. else {
  81. lists.push_front(Node(key, value));
  82. for (auto mitr = maps.begin(); mitr != maps.end(); mitr++) {
  83. mitr->second++;
  84. }
  85. maps.insert(make_pair(key, 0));
  86. }
  87. }
  88. }
  89. };
  90. int main(int argc, const char * argv[]) {
  91. // insert code here...
  92. LRUCache cache(5);
  93. cache.set(1, 10);
  94. cache.set(2, 20);
  95. cache.set(3, 30);
  96. //cout << "cache..." << cache.get(2) << endl;
  97. cache.set(4, 40);
  98. cache.set(5, 50);
  99. cache.set(8, 80);
  100. //cout << "cache..." << cache.get(1) << endl;
  101. cout << "cache..." << cache.get(5) << endl;
  102. return 0;
  103. }

如上面所说,我需要不停的去更新其的位置,这样才能根据正确的位置去获取到具体的结点信息;根据题目的要求,需要控制时间复杂度在1,所以需要需要一个哈希数组去记录其位置;但是我好像并没有做到,依旧使用了一个循环。。。

我的基础上优化

  1. struct node{
  2. int key;
  3. int value;
  4. node(int k, int v):key(k), value(v){}
  5. };
  6. /*
  7. * 注意整体思路是,使用双向list每次set或get一个元素时都把这个元素放到list的头部,无需统计每个元素的操作次数,实际上LRU的意思
  8. * 就是根据元素最后被访问的时间来决定替换哪个,故list中尾部元素即被替换.
  9. * STL技巧:1、使用map的find方法来判断key是否已经存在,返回值和map的end迭代器比较;
  10. 2、使用unordered_map,它是hash_map,存取时间都是O(1),用它存储元素的position迭代器,是为了方便splice函数调用
  11. * list.splice(position, list, element_pos)函数作用是把list的element_pos处的元素插入到position位置,本题中
  12. 为了移动元素到list头部
  13. */
  14. class LRUCache{
  15. int size;
  16. list<node> values;
  17. unordered_map<int, list<node>::iterator> positions;
  18. public:
  19. LRUCache(int capacity) {
  20. size = capacity;
  21. }
  22. int get(int key) {
  23. if(positions.find(key) != positions.end()){
  24. values.splice(values.begin(), values, positions[key]);
  25. positions[key] = values.begin();
  26. return values.begin()->value;
  27. }
  28. return -1;
  29. }
  30. void set(int key, int value) {
  31. if(positions.find(key) != positions.end()){
  32. values.splice(values.begin(), values, positions[key]); //移动被访问元素到头部
  33. values.begin()->value = value;
  34. positions[key] = values.begin(); //更新其位置,注意此处的position只是一个指针,当此key在list中被挤到其他位置后,positions里保存的位置也会跟着变化,因为它仅仅是一个指向该结点的指针
  35. }
  36. else if(values.size()<size){
  37. values.push_front(node(key, value));
  38. positions[key] = values.begin();
  39. }
  40. else{
  41. node last = values.back();
  42. values.pop_back();
  43. positions.erase(last.key);
  44. values.push_front(node(key, value));
  45. positions[key] = values.begin();
  46. }
  47. }
  48. };

将我的int下标,改成了纪录链表的迭代器,这下使用了splice会很方便,同时控制了时间复杂度。

总结

并没有。

LRU Cache 题解的更多相关文章

  1. LeetCode题解: LRU Cache 缓存设计

    LeetCode题解: LRU Cache 缓存设计 2014年12月10日 08:54:16 邴越 阅读数 1101更多 分类专栏: LeetCode   版权声明:本文为博主原创文章,遵循CC 4 ...

  2. 146. LRU Cache

    题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...

  3. LeetCode解题报告:LRU Cache

    LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should suppo ...

  4. LRU Cache leetcode java

    题目: Design and implement a data structure for Least Recently Used (LRU) cache. It should support the ...

  5. 【leetcode刷题笔记】LRU Cache

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  6. [LeetCode] LRU Cache 最近最少使用页面置换缓存器

    Design and implement a data structure for Least Recently Used (LRU) cache. It should support the fol ...

  7. 【leetcode】LRU Cache

    题目简述: Design and implement a data structure for Least Recently Used (LRU) cache. It should support t ...

  8. LeetCode:LRU Cache

    题目大意:设计一个用于LRU cache算法的数据结构. 题目链接.关于LRU的基本知识可参考here 分析:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::l ...

  9. LRU Cache实现

    最近在看Leveldb源码,里面用到LRU(Least Recently Used)缓存,所以自己动手来实现一下.LRU Cache通常实现方式为Hash Map + Double Linked Li ...

随机推荐

  1. HBase Coprocessor 剖析与编程实践(转载http://www.cnblogs.com/ventlam/archive/2012/10/30/2747024.html)

    HBase Coprocessor 剖析与编程实践 1.起因(Why HBase  Coprocessor) HBase作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执行求和. ...

  2. HDU 1054 Strategic Game 最小点覆盖

     最小点覆盖概念:选取最小的点数覆盖二分图中的所有边. 最小点覆盖 = 最大匹配数. 证明:首先假设我们求的最大匹配数为m,那么最小点覆盖必然 >= m,因为仅仅是这m条边就至少需要m个点.然后 ...

  3. AngularJS 从零开始学习(一)

    什么是AngularJS? AngularJS是一个把HTML(视图)绑定到JavaScript对象(模型)上的框架.当模型改变时,页面也能自动随之更新,反之亦然.当某个域的内容发生变化时,与之关联的 ...

  4. VIJOS P1647 不差钱 SBT

    [描述] 同学们一起看了小品<不差钱>,LX神突发奇想,想刁难一下十八居士,他让十八居士模拟一下点菜的过程. [输入格式] 输入第一行为一个数price,表示价钱大于price的菜赵本山都 ...

  5. 提升html5的性能体验系列之三流畅下拉刷新

    下拉刷新 为实现下拉刷新功能,大多H5框架都是通过DIV模拟下拉回弹动画,在低端android手机(Android4.4以下)上,DIV动画经常出现卡顿现象(特别是图文列表的情况).解决方案还是web ...

  6. AngularJS数据建模(转载)

    出处不明 我们知道,AngularJS并没有自带立等可用的数据建模方案.而是以相当抽象的方式,让我们在controller中使用JSON数据作为模 型.但是随着时间的推移和项目的成长,我意识到这种建模 ...

  7. AJAX开发技术--AJAX简介

    Asynchronous  JavaScript and XML,异步JavaScript和XML 主要目的用于页面的局部刷新.不用全部刷新,提高性能. 在AJAX中主要是通过XMLHttpReque ...

  8. Linux通过防火墙禁止IP来防止攻击

    1. iptables -I INPUT -s 211.1.0.0 -j DROP 禁止211.1.0.0这个IP访问服务器 2. iptables -I INPUT -s 211.1.0.0 -j ...

  9. html5中拨打电话代码

    <a href="tel:18600000000">给我打电话</a>   <a href="sms:18600000000"&g ...

  10. 转 SQL 基础--> NEW_VALUE 的使用

    --=============================== -- SQL 基础--> NEW_VALUE 的使用 --=============================== 通常 ...