题目描述:
运用你所掌握的数据结构,设计和实现一个 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
思路:
1、使用unordered_map和双向链表,存储数据
2、get() 数据后,将找到的数据添加到链表表头
3、put() 数据后,不需要删除,则在unordered_map中添加,以及在链表表头添加
4、put() 数据后,需要删除的话,删除链表表尾的数据,删除对应的unordered_map里的数据
代码:
struct DoubleList
{
int key;
int val;
DoubleList *pre;
DoubleList *next;
DoubleList():pre(nullptr),next(nullptr){}
DoubleList(int k,int v):key(k),val(v),pre(nullptr),next(nullptr){}
};
class LRUCache {
public:
int len;
unordered_map<int,int>ache;
DoubleList *head,*tail;
LRUCache(int capacity) {
len=capacity;
head = new DoubleList();
tail = new DoubleList();
head->next=tail;
tail->pre=head;
}
int get(int key) {
auto it=ache.find(key);
if(it!=ache.end())
{
moveHead(key);
return (it->second);
}
else
return -1;
}
void put(int key, int value) {
auto it=ache.find(key);
if(it!=ache.end())
{
it->second=value;
moveHead(key);
}
else
{
if(ache.size()==len)
{
int delete_key=deleteLast();
ache.erase(delete_key);
}
ache.insert({key,value});
add(key,value);
}
}
void add(int k,int v)
{
DoubleList *temp=new DoubleList(k,v);
temp->next=head->next;
head->next->pre=temp;
temp->pre=head;
head->next=temp;
}
int deleteLast()
{
int key;
DoubleList *temp = tail->pre;
tail->pre=tail->pre->pre;
tail->pre->next=tail;
key=temp->key;
delete temp;
return key;
}
void moveHead(int k)
{
DoubleList *temp;
temp=head->next;
while(temp!=tail)
{
if(temp->key==k)
{
temp->pre->next=temp->next;
temp->next->pre=temp->pre;
temp->next=head->next;
head->next->pre=temp;
head->next=temp;
temp->pre=head;
break;
}
temp=temp->next;
}
}
};