LeetCode刷题笔记——LRU算法
1. 什么是LRU算法?
LRU是一种缓存淘汰机制。
说到这里,我们顺便回顾一下常用的缓存算法都有哪些?
- LRU 最近最久未使用 最近使用时间
- LFU 最近最少使用 使用频率
- FIFO 先进先出
全称是Least Recently Used(最近最久未使用)
2.LRU算法数据结构是什么样子?
Leetcode上有一道LRU算法设计题目。让你设计数据结构,首先构造函数接收一个capacity参数作为缓存的最大容量,然后实现两个API:
- put(key,val)插入新的或者更新已有的键值对。
- get(key) 获取key对应的val,如果key不存在,返回-1.
get和put的时间复杂度必须是O(1)
首先我们看一下缓存的数据结构有什么特点:
- 需要实现根据key在O(1)时间找到value,很容易想到用hash表实现。
- 需要保存结点的前后关系,有两种备选方法:数组,链表。
- 需要在O(1)时间复杂度内插入删除结点。在给定一个结点情况下,要想实现从链表中删除这个结点,必须是双向链表。所以最终方案是hash表+双向链表。
- node中需要哪些信息?
- value必须的。
- key?也是需要的。我们执行put操作且缓存满的情况下,我们需要找到链表中的最后一个结点,把它从链表中删除,同时从hash表中删除。而hash表中只能通过key去查找,所以node中存放key也是必要的。
好了,到这里这个问题就分析清楚了。上代码:
首先定义结点数据结构:
struct BiListNode{
int key;
int val;
BiListNode *left,*right;
BiListNode(int k,int x){
key=k;
val=x;
left=NULL;
right=NULL;
}
BiListNode(){
key=-1;
val=-1;
left=NULL;
right=NULL;
}
};
LRU
class LRUCache {
public:
int capacity;
int size;
map<int,BiListNode*> listmap;
BiListNode *head;
LRUCache(int cap) {
capacity=cap;
head=new BiListNode();
head->left=head;
head->right=head;
size=0;
}
int get(int key) {
if(listmap.count(key)){
BiListNode *node=listmap[key];
if(head->right!=node){
node->left->right=node->right;
node->right->left=node->left;
node->left=head;
node->right=head->right;
head->right->left=node;
head->right=node;
}
return node->val;
}
else
return -1;
}
void put(int key, int value) {
BiListNode *node=NULL;
if(listmap.count(key)){
node=listmap[key];
// node after head, update value.
if(node->left==head){
node->val=value;
return ;
}
// pick up it and remove from list.
else{
node->left->right=node->right;
node->right->left=node->left;
node->val=value;
}
}
// key not in list
else{
if(size==capacity){
//node is the last
node=head->left;
listmap.erase(node->key);
node->val=value;
node->key=key;
listmap[key]=node;
node->left->right=head;
head->left=node->left;
}
else{
// create new node.
node=new BiListNode(key,value);
listmap[key]=node;
size++;
}
}
// insert node after head.
node->right=head->right;
node->left=head;
head->right->left=node;
head->right=node;
}
};