Skip to content

Files

Latest commit

4d6c701 · Feb 21, 2024

History

History

2622.Cache With Time Limit

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Feb 21, 2024
Feb 21, 2024
Apr 16, 2023

English Version

题目描述

编写一个类,它允许获取和设置键-值对,并且每个键都有一个 过期时间 。

该类有三个公共方法:

set(key, value, duration) :接收参数为整型键 key 、整型值 value 和以毫秒为单位的持续时间 duration 。一旦 duration 到期后,这个键就无法访问。如果相同的未过期键已经存在,该方法将返回 true ,否则返回 false 。如果该键已经存在,则它的值和持续时间都应该被覆盖。

get(key) :如果存在一个未过期的键,它应该返回这个键相关的值。否则返回 -1 。

count() :返回未过期键的总数。

 

示例 1:

输入: 
actions = ["TimeLimitedCache", "set", "get", "count", "get"]
values = [[], [1, 42, 100], [1], [], [1]]
timeDeays = [0, 0, 50, 50, 150]
输出: [null, false, 42, 1, -1]
解释:
在 t=0 时,缓存被构造。
在 t=0 时,添加一个键值对 (1: 42) ,过期时间为 100ms 。因为该值不存在,因此返回false。
在 t=50 时,请求 key=1 并返回值 42。
在 t=50 时,调用 count() ,缓存中有一个未过期的键。
在 t=100 时,key=1 到期。
在 t=150 时,调用 get(1) ,返回 -1,因为缓存是空的。

示例 2:

输入:
actions = ["TimeLimitedCache", "set", "set", "get", "get", "get", "count"]
values = [[], [1, 42, 50], [1, 50, 100], [1], [1], [1], []]
timeDelays = [0, 0, 40, 50, 120, 200, 250]
输出: [null, false, true, 50, 50, -1]
解释:
在 t=0 时,缓存被构造。
在 t=0 时,添加一个键值对 (1: 42) ,过期时间为 50ms。因为该值不存在,因此返回false。
当 t=40 时,添加一个键值对 (1: 50) ,过期时间为 100ms。因为一个未过期的键已经存在,返回 true 并覆盖这个键的旧值。
在 t=50 时,调用 get(1) ,返回 50。
在 t=120 时,调用 get(1) ,返回 50。
在 t=140 时,key=1 过期。
在 t=200 时,调用 get(1) ,但缓存为空,因此返回 -1。
在 t=250 时,count() 返回0 ,因为缓存是空的,没有未过期的键。

 

提示:

  • 0 <= key, value <= 109
  • 0 <= duration <= 1000
  • 1 <= actions.length <= 100
  • actions.length === values.length
  • actions.length === timeDelays.length
  • 0 <= timeDelays[i] <= 1450
  • actions[i] 是 "TimeLimitedCache"、"set"、"get" 和 "count" 中的一个。
  • 第一个操作始终是 "TimeLimitedCache" 而且一定会以 0 毫秒的延迟立即执行

解法

方法一:哈希表

我们用哈希表 c a c h e 记录键值对,其中键为整型键 k e y ,值为一个数组,数组的第一个元素为整型值 v a l u e ,第二个元素为元素的过期时间 e x p i r e

我们实现一个 removeExpire 方法,用于删除过期的键值对。在 setgetcount 方法中,我们先调用 removeExpire 方法,然后再进行相应的操作。

时间复杂度为 O ( 1 ) ,空间复杂度为 O ( n ) 。其中 n 为哈希表 c a c h e 的大小。

class TimeLimitedCache {
    private cache: Map<number, [value: number, expire: number]> = new Map();

    constructor() {}

    set(key: number, value: number, duration: number): boolean {
        this.removeExpire();
        const ans = this.cache.has(key);
        this.cache.set(key, [value, this.now() + duration]);
        return ans;
    }

    get(key: number): number {
        this.removeExpire();
        return this.cache.get(key)?.[0] ?? -1;
    }

    count(): number {
        this.removeExpire();
        return this.cache.size;
    }

    private now(): number {
        return new Date().getTime();
    }

    private removeExpire(): void {
        const now = this.now();
        for (const [key, [, expire]] of this.cache) {
            if (expire <= now) {
                this.cache.delete(key);
            }
        }
    }
}

/**
 * Your TimeLimitedCache object will be instantiated and called as such:
 * var obj = new TimeLimitedCache()
 * obj.set(1, 42, 1000); // false
 * obj.get(1) // 42
 * obj.count() // 1
 */