问题
思路
参考了[O(1) unordered_map + list + splice]
参考者代码的思路非常清晰。
首先,插入和获取的时间复杂度在O(1),不能用deque去实现。否则无法到达常数。采用链表,插入,删除的时间复杂度都是o(1)。需要双向链表,可以自己实现。可以使用stl::list. 由于链表不支持随机访问,所以,做一次哈希。
代码
class LRUCache {
public:
LRUCache(int capacity) : cap_(capacity) {}
int get(int key) {
if( cache_map_.find(key) == cache_map_.end() ) return -1;
else{
int val = cache_map_[key]->val;
cache_list_.splice( cache_list_.begin(), cache_list_, cache_map_[key] );
return val;
}
}
void put(int key, int value) {
if( cache_map_.find(key) != cache_map_.end() ){
cache_map_[key]->val = value;
cache_list_.splice(cache_list_.begin(), cache_list_, cache_map_[key]);
}else{
element e(key, value);
if(cache_list_.size() < cap_){
cache_list_.push_front(e);
cache_map_[key] = cache_list_.begin();
}else{
cache_map_.erase(cache_list_.back().key);
cache_list_.pop_back();
cache_list_.push_front(e);
cache_map_[key] = cache_list_.begin();
}
}
}
private:
struct element{
int key;
int val;
element(): key(0),val(0){}
element(int k, int v) : key(k), val(v){}
};
std::list<element> cache_list_;
std::unordered_map< int, std::list<element>::iterator > cache_map_;
int cap_;
};
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
代码1
自己实现了循环双链表,注意pop_back的时候,别忘了从哈希表删除。
class LRUCache {
public:
LRUCache(int capacity) : cap_(capacity), size_(0) {
head_ = tail_ = new Node();
assert(head_);
assert(cap_);
}
int get(int key) {
std::cout << "get: " << key << std::endl;
if( cache_map_.find(key) == cache_map_.end() ) return -1;
else{
CacheList p = cache_map_[key];
move_to_head(p);
return p->val;
}
}
void put(int key, int value) {
std::cout << "put: " << key << "," << value << std::endl;
if( cache_map_.find(key) != cache_map_.end() ){
CacheList p = cache_map_[key];
p->val = value;
move_to_head(p);
}else{
CacheList p = new Node();
p->key = key;
p->val = value;
++size_;
if(size_ <= cap_){
insert_head(p);
cache_map_[key] = p;
}else{
size_ = cap_;
cache_map_.erase(tail_->key);
delete_tail();
insert_head(p);
cache_map_[key] = p;
}
}
}
~LRUCache() { delete head_; }
private:
struct Node {
int key;
int val;
Node* next;
Node* prev;
Node() { memset(this, 0, sizeof(Node));}
};
typedef Node* CacheList;
CacheList head_;
CacheList tail_;
int cap_;
int size_;
unordered_map<int, CacheList> cache_map_;
private:
void move_to_head(CacheList p){
if( head_ == tail_ ) return ;
if( head_->next == p ) return ;
else{
if(p == tail_){
tail_ = tail_->prev;
tail_->next = NULL;
}
else{
CacheList pre = p->prev;
CacheList nex = p->next;
pre->next = nex;
nex->prev = pre;
}
insert_head(p);
}
}
void insert_head(CacheList p){
CacheList q = head_->next;
p->next = q;
p->prev = head_;
head_->next = p;
if(q) q->prev = p;
else tail_ = p;
}
void delete_tail(){
if(head_ == tail_) return;
CacheList p = tail_;
tail_ = tail_->prev;
tail_->next = NULL;
delete p;
}
};
代码2
bug在于,要区别两类迭代器。不是一回事!
class LRUCache {
public:
LRUCache(int capacity) {
cap_ = capacity;
}
int get(int key) {
if( cache_map_.find(key) == cache_map_.end() ) return -1;
else{
Iter it = cache_map_[key];
// move to head
cache_list_.splice( cache_list_.begin(), cache_list_, it );
// return value
return it->second;
}
}
void put(int key, int value) {
if( cache_map_.find(key) != cache_map_.end() ){
Iter it = cache_map_[key];
// update the value
it->second = value;
// move to head
cache_list_.splice( cache_list_.begin(), cache_list_, it );
}
else{
if( cache_list_.size() == cap_ ){
cache_map_.erase( cache_list_.back().first );
cache_list_.pop_back();
}
Node node(key, value);
cache_list_.push_front(node);
cache_map_[key] = cache_list_.begin();
}
}
private:
typedef pair<int, int> Node;
typedef list<Node>::iterator Iter;
list<Node> cache_list_;
unordered_map<int, Iter> cache_map_;
int cap_;
};