难度:中等
题目描述
设计和实现一个 LRU (最近最少使用) 缓存机制。它应该支持以下操作:获取数据 get
和写入数据 put
。
- 获取数据
get(key)
:如果密钥 (key) 存在于缓存中,则获取密钥的值(总是正数),否则返回 -1。 - 写入数据
put(key, value)
:如果密钥不存在,则写入其数据值。当缓存容量达到上限时,它应该在写入新数据之前删除最近最少使用的数据值,从而为新的数据值留出空间。
示例
javascript
let cache = new LRUCache(2); // 缓存容量为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
为什么推荐这道题
- 这是一个经典的前端面试题,考察对数据结构的理解
- 需要结合哈希表和双向链表来实现高效操作
- 能够练习 JavaScript 的 Map 或 Object 的使用
- 理解缓存机制对前端性能优化很有帮助
解题思路提示
- 使用 Map 来存储键值对(Map 能记住键的原始插入顺序)
- 当获取一个键时,先删除再重新插入以更新其使用顺序
- 当插入新键值对且容量已满时,删除 Map 中的第一个键(即最久未使用的)
LRU 缓存机制的 JavaScript 实现
以下是使用 JavaScript 的 Map 数据结构实现的 LRU 缓存解决方案:
javascript
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map(); // 使用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);
return value;
}
put(key, value) {
// 如果键已存在,先删除
if (this.cache.has(key)) {
this.cache.delete(key);
}
// 设置新值
this.cache.set(key, value);
// 如果超出容量,删除最久未使用的(即Map中的第一个键)
if (this.cache.size > this.capacity) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
}
}
使用构造函数实现的 LRU 缓存
以下是使用传统构造函数和原型链方式实现的 LRU 缓存方案:
javascript
function LRUCache(capacity) {
this.capacity = capacity;
this.cache = new Map(); // 使用Map保存键值对,Map会记住键的原始插入顺序
}
LRUCache.prototype.get = function(key) {
if (!this.cache.has(key)) {
return -1;
}
// 获取值
const value = this.cache.get(key);
// 删除并重新插入,以更新其为最新使用
this.cache.delete(key);
this.cache.set(key, value);
return value;
};
LRUCache.prototype.put = function(key, value) {
// 如果键已存在,先删除
if (this.cache.has(key)) {
this.cache.delete(key);
}
// 设置新值
this.cache.set(key, value);
// 如果超出容量,删除最久未使用的(即Map中的第一个键)
if (this.cache.size > this.capacity) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
};