leetcode LRU Cache

来源:互联网 发布:nginx 反向代理 原理 编辑:程序博客网 时间:2024/04/29 17:54

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.

I wrote a wrong code like this :

class LRUCache { public:  int size;  list<int> cacheList;  unordered_map<int, list<int>::iterator> cacheMap;  LRUCache(int capacity) {    size = capacity;  }  int get(int key) {    if (cacheMap.find(key) == cacheMap.end())      return -1;    cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);    cacheMap[key] = cacheList.begin();    return *(cacheList.begin());  }  void set(int key, int value) {    if (cacheMap.find(key) == cacheMap.end()) {      cacheList.push_front(value);      cacheMap.insert(make_pair(key, cacheList.begin()));      if (cacheList.size() > size) {        //cacheMap.erase(cacheList.back());        cacheList.pop_back();      }    }           else {      cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);      *(cacheList.begin()) = value;      cacheMap[key] = cacheList.begin();    }  }};

Some comments:

1. Erase needs the parameters iterator or key, so list<int> isn't enough. Some nodes are still in map but not in list, so Runtime error. 

2. 

cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);

函数有以下三种声明:

void splice ( iterator position, list<T,Allocator>& x );  // 

void splice ( iterator position, list<T,Allocator>& x, iterator i );

void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );

函数说明:在list间移动元素:

将x的元素移动到目的list的指定位置,高效的将他们插入到目的list并从x中删除。

目的list的大小会增加,增加的大小为插入元素的大小。x的大小相应的会减少同样的大小。

前两个函数不会涉及到元素的创建或销毁。第三个函数会。

指向被删除元素的迭代器会失效。

参数:

position

目的list的位置,用来标明 插入位置

x

源list、

first,last

x里需要被移动的元素的迭代器。区间为[first, last).

包含first指向的元素,不包含last指向的元素。


3. front(), back() return value_types, but begin() and end() return iterators. 

  • Iterators:
    • list.begin() 回传指向第一个元素的 Iterator。
    • list.end() 回传指向最末元素的下一个位置的 Iterator。
    • list.rbegin() 回传指向最末个元素的反向 Iterator。
    • list.rend() 回传指向第一个元素的前一个位置的反向 Iterator。
  • Capacity/Size:
    • list.empty() 若list内部为空,则回传true值。
    • list.size() 回传list内实际的元素个数。
    • lsit.resize() 重新分派list的长度。
  • Element Access
    • list.front() 存取第一个元素。
    • list.back() 存取最末个元素。
  • Modify methods
    • list.push_front() 增加一个新的元素在 list 的前端。
    • list.pop_front() 删除 list 的第一个元素。
    • list.push_back() 增加一个新的元素在 list 的尾端。
    • list.pop_back() 删除 list 的最末个元素。


Right Code:

class CacheNode { public:  int key, value;  CacheNode(int key, int value):key(key), value(value) {}};class LRUCache { public:  int size;  list<CacheNode> cacheList;  unordered_map<int, list<CacheNode>::iterator> cacheMap;  LRUCache(int capacity) {    size = capacity;  }  int get(int key) {    if (cacheMap.find(key) == cacheMap.end())      return -1;    cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);    cacheMap[key] = cacheList.begin();    return cacheList.begin()->value;  }  void set(int key, int value) {    if (cacheMap.find(key) == cacheMap.end()) {      cacheList.push_front(CacheNode(key,value));      cacheMap.insert(make_pair(key, cacheList.begin()));      if (cacheList.size() > size) {        cacheMap.erase(cacheList.back().key);        cacheList.pop_back();      }    }           else {      cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]);      cacheList.begin()->value = value;      cacheMap[key] = cacheList.begin();    }  }};


原创粉丝点击