leetcode 146. LRU缓存机制
题目详情
题目链接
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作: 获取数据 get 和 写入数据 put 。
获取数据 get(key) - 如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。
写入数据 put(key, value) - 如果密钥已经存在,则变更其数据值;如果密钥不存在,则插入该组「密钥/数据值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。
- 进阶:
你是否可以在 O(1) 时间复杂度内完成这两种操作?- 示例:
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得密钥 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得密钥 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
我的代码
class LRUCache {
private:
int capacity, cur;
map<int, int> datas;
list<int> keys;
map<int, list<int>::iterator> locs;
public:
LRUCache(int capacity) {
this->capacity = capacity, cur = 0;
}
int get(int key) {
if (!datas.count(key)) {
return -1;
}
keys.erase(locs[key]);
keys.push_back(key);
locs[key] = --keys.end();
return datas[key];
}
void put(int key, int value) {
if (datas.count(key)) {
keys.erase(locs[key]);
keys.push_back(key);
locs[key] = --keys.end();
} else if (cur < capacity) {
++cur;
keys.push_back(key);
locs[key] = --keys.end();
} else {
keys.push_back(key);
locs[key] = --keys.end();
datas.erase(keys.front());
keys.erase(keys.begin());
}
datas[key] = value;
}
};
/**
* 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);
*/
我的成绩
执行结果:通过
执行用时 : 588 ms, 在所有 C++ 提交中击败了5.03%的用户
内存消耗 : 36.8 MB, 在所有 C++ 提交中击败了100.00%的用户
一些想法
本道题我使用了一个map和一个数组,map用来记录key和alue,数组用来记录key的位置,并在set和put时做相应的更新。
执行用时为 0 ms 的范例
struct bid_ListNode {
bid_ListNode* next;
bid_ListNode* last;
int val;
int key;
bid_ListNode(int key, int value):key(key),val(value), next(NULL), last(NULL){};
};
class LRUCache {
int cap =0;
bid_ListNode* head = NULL;
bid_ListNode* tail = NULL;
unordered_map<int, bid_ListNode*> index;
int current_cap = 0;
// 从链表里删除,必定存在
void remove(bid_ListNode* ptr) {
bid_ListNode* pre = ptr->last;
bid_ListNode* nex = ptr->next;
pre->next = nex;
nex->last = pre;
}
// 插入新的在末尾
void insert_tail(bid_ListNode* ptr){
bid_ListNode* pre = tail->last;
pre ->next = ptr;
ptr->next = tail;
ptr->last = pre;
tail->last = ptr;
}
public:
LRUCache(int capacity) {
cap = capacity;
current_cap = 0;
// 初始化链表
if(capacity ==0)
return ;
head = new bid_ListNode(0,0);
tail = new bid_ListNode(0,0);
tail->last = head;
head->next = tail;
}
int get(int key) {
if(index.find(key) == index.end())
return -1;
bid_ListNode* ptr = index[key];
//更新ptr的
put(ptr->key, ptr->val);
return ptr->val;
}
void put(int key, int value) {
// 当前存在,更新key, 插到表头
if(index.find(key) != index.end()) {
bid_ListNode* ptr = index[key];
ptr->val = value;
// 从中间删除
remove(ptr);
//插在末尾
insert_tail(ptr);
} else {
bid_ListNode* ptr = new bid_ListNode(key,value);
index[key] = ptr;
// 当前不存在,还没有满,插入在末尾
if(current_cap < cap){
//插在末尾
insert_tail(ptr);
current_cap ++;
} else {
// 当前不存在,满了
//删除头部,包括index
bid_ListNode* curr_head = head->next;
index.erase(curr_head->key);
remove(curr_head);
//插入尾部
insert_tail(ptr);
}
}
}
};
/**
* 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);
*/
思考
范例用了链表,使得在做更新时可以减少更新时间。