146. LRU 缓存机制

难度:中等

题目描述

设计和实现一个 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

为什么推荐这道题

  1. 这是一个经典的前端面试题,考察对数据结构的理解
  2. 需要结合哈希表和双向链表来实现高效操作
  3. 能够练习 JavaScript 的 Map 或 Object 的使用
  4. 理解缓存机制对前端性能优化很有帮助

解题思路提示

  1. 使用 Map 来存储键值对(Map 能记住键的原始插入顺序)
  2. 当获取一个键时,先删除再重新插入以更新其使用顺序
  3. 当插入新键值对且容量已满时,删除 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);
  }
};
相关推荐
恋猫de小郭24 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端