推荐答案
// www.javascriptcn.com code example
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map(); // 使用Map存储,保持插入顺序
}
get(key) {
if (!this.cache.has(key)) {
return -1;
}
const value = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, value); // 访问后,将 key 移到末尾,表示最近使用过
return value;
}
put(key, value) {
if(this.cache.has(key)){
this.cache.delete(key);
}
this.cache.set(key,value)
if (this.cache.size > this.capacity) {
this.cache.delete(this.cache.keys().next().value); // 移除最久未使用的(队头)
}
}
}
// 使用示例
const lruCache = new LRUCache(2);
lruCache.put(1, 1);
lruCache.put(2, 2);
console.log(lruCache.get(1)); // 返回 1
lruCache.put(3, 3); // 移除key 2
console.log(lruCache.get(2)); // 返回 -1 (未找到)
lruCache.put(4,4) //移除key 1
console.log(lruCache.get(1)); // 返回-1
console.log(lruCache.get(3)); //返回3
console.log(lruCache.get(4)); //返回4本题详细解读
缓存策略:LRU
LRU (Least Recently Used) 是一种常见的缓存淘汰策略。其核心思想是:当缓存空间不足时,优先淘汰最近最少使用的数据,保留最近经常使用的数据。
实现思路
数据结构选择:
- 使用
Map数据结构来存储缓存数据。Map可以保持插入顺序,这对于实现 LRU 策略非常重要。 Map的get,set,delete方法时间复杂度均为 O(1),满足高效访问要求。
- 使用
核心操作:
get(key):- 如果
key存在于Map中:- 获取
key对应的value。 - 将
key从Map中删除。 - 将
key重新插入到Map的末尾(表示最近使用)。 - 返回
value。
- 获取
- 如果
key不存在,返回-1。
- 如果
put(key, value):- 如果
key存在于Map中,先删除该key。 - 将
key和value插入到Map的末尾(表示最近使用)。 - 如果
Map的大小超过了capacity,则删除Map中第一个元素(即最久未使用)。这里使用this.cache.keys().next().value获取队头key。
- 如果
代码解析
constructor(capacity):- 初始化缓存的容量
capacity和一个Map实例cache。
- 初始化缓存的容量
get(key):- 检查
key是否存在于cache中。 - 如果存在,获取
value,并将其对应的key移动到cache的末尾,然后返回value。 - 如果不存在,返回
-1。
- 检查
put(key, value):- 如果
key存在于Map中,先删除该key。 - 将
key和value插入到cache的末尾。 - 如果缓存已满,删除
cache中最老的(第一个)key-value对。
- 如果
为什么选择 Map?
- 保持插入顺序:
Map对象会记住键的原始插入顺序。这对于实现 LRU 策略至关重要,因为我们需要知道哪个元素是最近最少使用的。 - 高效查找:
Map对象的get,set,delete方法时间复杂度均为 O(1),可以快速访问和操作缓存中的元素。 - **方便删除最早插入元素:**可以通过
this.cache.keys().next().value方便的获取到最先插入的key,再通过delete删除。
时间复杂度
get(key): O(1)put(key, value): O(1)
空间复杂度
- O(capacity) 缓存最多存储capacity个元素