编程题之设计LRU缓存结构
题目描述:
设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能:
- set (key, value):将记录(key, value)插入该结构
- get(key) :返回key对应的value值
[要求]
- set和get方法的时间复杂度为O(1)。
- 某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
- 当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
若opt=1,接下来两个整数下x,y,表示set(x,y)。
若opt=2,接下来一个整数x,表示get(x),若未出现过或已被移除,则返回-1。
对于每个操作2,输出一个答案。
输入:
[ [1,1,1] , [1,2,2] , [1,3,2] , [2,1] , [1,4,4] , [2,2] ], 3
返回值:
[ 1, -1]
思路:
哈希表 + 双向链表
C++ 用unordered_map<int, DLinkedNode*> cache表示哈希表。
python 用dict()函数生成字典表示哈希表。
C++代码
struct DLinkedNode {
int key, value;
DLinkedNode* prev;
DLinkedNode* next;
DLinkedNode(): key(0), value(0), prev(nullptr), next(nullptr){}
DLinkedNode(int _key, int _value): key(_key), value(_value), prev(nullptr), next(nullptr){}
};
class Solution {
public:
/**
* lru design
* @param operators int整型vector<vector<>> the ops
* @param k int整型 the k
* @return int整型vector
*/
vector<int> LRU(vector<vector<int> >& operators, int k) {
// write code here
vector<int> result;
cap = k;
size = 0;
head = new DLinkedNode();
tail = new DLinkedNode();
head->next = tail;
tail->prev = head;
result.reserve(operators.size());
if(k!=0) {
for(const vector<int>& opt:operators) {
if(opt[0]==1) put(opt[1],opt[2]);
else if(opt[0]==2) result.push_back(get(opt[1]));
}
}
return result;
}
int get(int key){
if(!cache.count(key)){
return -1;
}
//如果key存在,先通过哈希表定位,再移到头部
DLinkedNode* node = cache[key];
moveToHead(node);
return node->value;
}
void put(int key, int value){
if(!cache.count(key)){
//如果key不存在,创建一个新的节点
DLinkedNode* node = new DLinkedNode(key, value);
//添加进哈希表
cache[key] = node;
//添加至双向链表的头部
addToHead(node);
++size;
if(size > cap){
//如果超出容量,删除双向链表的尾部节点
DLinkedNode* removed = removeTail();
//删除哈希表中对应的项
cache.erase(removed->key);
delete removed;
--size;
}
}
else{
//如果key存在,先通过哈希表定位,再修改value,并移到头部
DLinkedNode* node = cache[key];
node->value = value;
moveToHead(node);
}
}
void addToHead(DLinkedNode* node){
node->prev = head;
node->next = head->next;
head->next->prev = node;
head->next = node;
}
void removeNode(DLinkedNode* node){
node->prev->next = node->next;
node->next->prev = node->prev;
}
void moveToHead(DLinkedNode* node){
removeNode(node);
addToHead(node);
}
DLinkedNode* removeTail(){
DLinkedNode* node = tail->prev;
removeNode(node);
return node;
}
private:
unordered_map<int, DLinkedNode*> cache;
DLinkedNode* head;
DLinkedNode* tail;
int size;
int cap;
};
python代码
#
# lru design
# @param operators int整型二维数组 the ops
# @param k int整型 the k
# @return int整型一维数组
#
class DLinkedNode:
def __init__(self, key=0, value=0):
self.key = key
self.value = value
self.prev = None
self.next = None
class Solution:
def __init__(self):
#创建一个空字典
self.cache = dict()
#使用伪头部和伪尾部节点
self.head = DLinkedNode()
self.tail = DLinkedNode()
self.head.next = self.tail
self.tail.prev = self.head
self.cap = 0
self.size = 0
def get(self, key):
if key not in self.cache:
return -1
# 如果key存在,先通过哈希表定位,再移到头部
node = self.cache[key]
self.moveToHead(node)
return node.value
def put(self, key, value):
if key not in self.cache:
#如果key不存在,创建一个新的节点
node = DLinkedNode(key, value)
#添加进哈希表
self.cache[key] = node
#添加至双向链表的头部
self.addToHead(node)
self.size += 1
if self.size > self.cap:
#如果超出容量,删除双向链表的尾部节点
removed = self.removeTail()
#删除哈希表中对应的项
self.cache.pop(removed.key)
self.size -= 1
else:
#如果key存在,先通过哈希表定位,再修改value,并移到头部
node = self.cache[key]
node.value = value
self.moveToHead(node)
def addToHead(self, node):
node.prev = self.head
node.next = self.head.next
self.head.next.prev = node
self.head.next = node
def removeNode(self, node):
node.prev.next = node.next
node.next.prev = node.prev
def moveToHead(self, node):
self.removeNode(node)
self.addToHead(node)
def removeTail(self):
node = self.tail.prev
self.removeNode(node)
return node
def LRU(self , operators , k ):
# write code here
self.cap = k
res = []
for x in operators:
if x[0] == 1:
self.put(x[1], x[2])
elif x[0] == 2:
res.append(self.get(x[1]))
return res
python实现在牛客网上运行超时!!!