题目连接
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]); } };