题目连接
https://leetcode.com/problems/lru-cache/
LRU Cache
Description
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设计一个数据结构,它支持两个操作
(1)get(key):如果key在cache中,则返回对应的value值,否则返回-1
(2)set(key,value):如果key不在cache中,则将该(key,value)插入cache中(注意,如果 cache已满,则必须把最近最久未使用的元素从cache中删除);如果key在cache中,则重置value的值。
思路:用一个变量表示时间戳,每当插入key时,时间戳++,当插入元素已存在数据中更新它的value时也要更新他的时间戳。若cache已满先要删除时间戳最早的元素,再插入新元素。
当get元素时,它的时间戳必须更新(毕竟这个元素正在访问中。。)
思路理清了,代码实现就很简单了。。
用map让时间戳与key对应,用平衡树存储key,value, 时间戳。。
class LRUCache {
private:
const int INF = ~0u >> 1;
public:
LRUCache() = default;
LRUCache(int capacity) {
idx = 0, size = capacity;
null = new Node(INF, INF, -1, 0, NULL);
root = null;
}
~LRUCache() { clear(root); root = NULL; }
int get(int key) {
Node *x = find(key);
if (x->s) {
MP.erase(MP.find(x->idx));
MP[idx] = x->key;
x->idx = idx++;
}
return !x->s ? -1 : x->val;
}
void set(int key, int value) {
Node *x = find(key);
if (!x->s && root->s != this->size) {
insert(root, key, value, idx);
MP[idx++] = key;
} else {
if (key == x->key) {
x->val = value;
MP.erase(MP.find(x->idx));
MP[idx] = x->key;
x->idx = idx++;
} else {
auto ret = MP.begin();
erase(root, ret->second);
MP.erase(ret);
insert(root, key, value, idx);
MP[idx++] = key;
}
}
}
private:
int idx, size;
private:
map<int, int> MP;
struct Node {
int key, val, idx, s;
Node *ch[2];
Node(int i, int j, int k, int l, Node *p) {
key = i, val = j, idx = k, s = l;
ch[0] = ch[1] = p;
}
inline bool cmp(int v) const {
return v > key;
}
inline void push_up() {
s = ch[0]->s + ch[1]->s + 1;
}
}*root, *null;
inline void rotate(Node *&x, bool d) {
Node *k = x->ch[!d]; x->ch[!d] = k->ch[d]; k->ch[d] = x;
k->s = x->s, x->push_up(), x = k;
}
inline void Maintain(Node *&x, bool d) {
if (!x->ch[d]->s) return;
if (x->ch[d]->ch[d]->s > x->ch[!d]->s) rotate(x, !d);
else if (x->ch[d]->ch[!d]->s > x->ch[!d]->s) rotate(x->ch[d], d), rotate(x, !d);
else return;
Maintain(x, 0), Maintain(x, 1);
}
inline void insert(Node *&x, int key, int val, int idx) {
if (!x->s) { x = new Node(key, val, idx, 1, null); return; }
x->s++;
bool d = x->cmp(key);
insert(x->ch[d], key, val, idx);
x->push_up();
Maintain(x, d);
}
inline void erase(Node *&x, int key) {
if (!x->s) return;
x->s--;
bool d = x->cmp(key);
if (x->key == key) {
Node *ret = NULL;
if (!x->ch[0]->s || !x->ch[1]->s) {
ret = x;
x = ret->ch[0]->s ? ret->ch[0] : x->ch[1];
delete ret;
} else {
ret = x->ch[1];
for (; ret->ch[0]->s; ret = ret->ch[0]);
x->key = ret->key, x->val = ret->val, x->idx = ret->idx;
erase(x->ch[1], x->key);
}
} else {
erase(x->ch[d], key);
}
if (x->s) x->push_up();
}
inline Node* find(int key) {
Node *x = root;
while (x->s && x->key != key) x = x->ch[key > x->key];
return x;
}
inline void clear(Node *x) {
if (!x->s) return;
clear(x->ch[0]);
delete x;
clear(x->ch[1]);
}
};