使用双向链表解决此问题,因为双向链表可以很容易的获取到头结点和尾结点。题目要求 get 和 put 要在O(1)的时间复杂度下运行,很显然要用set或map。根据题意,应使用map。 unordered_map<int,Node*> cache; map->first为Node中的key,可以根据这个key在map中查找元素是否存在。
class LRUCache {
public:
//定义双向链表的结构
struct Node
{
int key;
int value;
Node* prev;
Node* next;
Node(int k,int v) : key(k),value(v),prev(nullptr),next(nullptr){}
};
//初始化双向链表
LRUCache(int capacity) {
this->capacity = capacity;
head = new Node(0,0);
tail = new Node(0,0);
head->next = tail;
tail->prev = head;
}
//向双向链表中存储数据
//如果存在,则返回对应的值
int get(int key) {
//查找到了
if(cache.find(key)!=cache.end())
{
//查找到之后需要把这个元素放到表头,并返回value
Node* node = cache[key];
moveToHead(node);
return node->value;
}
return -1;
}
//向双向链表中存储元素,若存在改变其数据值,并把这个移动到头部,若不存在则插入,把最后一个元素删除,插入在头部。
//若插入后导致数量超过capacity,把最后一个删掉
void put(int key, int value) {
//若找到了
if(cache.find(key)!= cache.end())
{
Node* node = cache[key];
node->value = value;
moveToHead(node);
}
//没有找到
else
{
Node* node = new Node(key,value);
//没找到的话需要新建一个节点插入,但是要先判断下插入下是不是会超过capacity
//如果超过
if(cache.size()+1>capacity)
{
//将最后一个移除
Node* tailNode = removeTail();
cache.erase(tailNode->key);
delete tailNode;
}
//将新节点添加到表头
cache[key] = node;
addHead(node);
}
}
//将该节点移动到头结点
void moveToHead(Node* node)
{
removeNode(node);
addHead(node);
}
//移除某个节点
void removeNode(Node* node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
//将node添加到双向链表头部
void addHead(Node* node)
{
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
}
//删除最后一个节点,并返回该节点,因为要通过该节点删除cache中的元素
Node* removeTail()
{
Node* tailNode = tail->prev;
removeNode(tailNode);
return tailNode;
}
private:
int capacity;
Node* head;
Node* tail;
unordered_map<int,Node*> cache;
};
/**
* 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);
*/