算法-LRU缓存(可设置过期时间)

loading 2024年08月24日 20次浏览

大疆笔试遇到这道题,记录一下:

/**
 * @param {number} capacity
 */
var LRUCache = function(capacity) {
    this.map = new Map();
    this.capacity = capacity;
    this.timers = new Map(); // 用于存储定时器
};

/** 
 * @param {number} key
 * @return {number}
 */
LRUCache.prototype.get = function(key) {
    if (!this.map.has(key)) return -1;
    let temp = this.map.get(key);
    this.map.delete(key);
    this.map.set(key, temp);
    return temp;
};

/** 
 * @param {number} key 
 * @param {number} value
 * @param {number} [ttl] - 过期时间(毫秒)
 * @return {void}
 */
LRUCache.prototype.put = function(key, value, ttl) {
    if (this.map.has(key)) {
        this.map.delete(key);
        clearTimeout(this.timers.get(key)); // 清除旧的定时器
    }
    this.map.set(key, value);

    if (ttl !== undefined) {
        const timer = setTimeout(() => {
            this.map.delete(key);
            this.timers.delete(key);
        }, ttl);
        this.timers.set(key, timer);
    }

    if (this.map.size > this.capacity) {
        const oldestKey = [...this.map.keys()][0];
        this.map.delete(oldestKey);
        if (this.timers.has(oldestKey)) {
            clearTimeout(this.timers.get(oldestKey));
            this.timers.delete(oldestKey);
        }
    }
};

// 测试
var cache = new LRUCache(2);
cache.put(1, 1, 5000); // 设置 key 1 的过期时间为 5 秒
cache.put(2, 2);
console.log(cache.get(1)); // 返回 1
setTimeout(() => {
    console.log(cache.get(1)); // 返回 -1,因为 key 1 已经过期
}, 6000);
cache.put(3, 3); // 这个操作会使 key 2 被移除
console.log(cache.get(2)); // 返回 -1,因为 key 2 被移除
console.log(cache.get(3)); // 返回 3
  • 新增 timers 属性
    用于存储每个键的定时器。
  • 修改 put 方法
    如果键已经存在,先删除旧的键并清除旧的定时器。
    如果设置了 ttl(过期时间),使用 setTimeout 创建一个定时器,当时间到达时自动删除该键。
    如果缓存超过容量,删除最老的键,并清除其定时器(如果存在)。