likes
comments
collection
share

【算法】基于时间的键值存储难度:中等; 题目: 设计一个基于时间的键值数据结构,该结构可以在不同时间戳存储对应同一个键的

作者站长头像
站长
· 阅读数 55

难度:中等;

题目:

设计一个基于时间的键值数据结构,该结构可以在不同时间戳存储对应同一个键的多个值,并针对特定时间戳检索键对应的值。

实现 TimeMap 类:

  • TimeMap() 初始化数据结构对象
  • void set(String key, String value, int timestamp) 存储给定时间戳 timestamp 时的键 key 和值 value
  • String get(String key, int timestamp) 返回一个值,该值在之前调用了 set,其中 timestamp_prev <= timestamp 。如果有多个这样的值,它将返回与最大 timestamp_prev 关联的值。如果没有值,则返回空字符串("")。

示例 1:

输入:
["TimeMap", "set", "get", "get", "set", "get", "get"]
[[], ["foo", "bar", 1], ["foo", 1], ["foo", 3], ["foo", "bar2", 4], ["foo", 4], ["foo", 5]]
输出:
[null, null, "bar", "bar", null, "bar2", "bar2"]

解释:
TimeMap timeMap = new TimeMap();
timeMap.set("foo", "bar", 1);  // 存储键 "foo" 和值 "bar" ,时间戳 timestamp = 1   
timeMap.get("foo", 1);         // 返回 "bar"
timeMap.get("foo", 3);         // 返回 "bar", 因为在时间戳 3 和时间戳 2 处没有对应 "foo" 的值,所以唯一的值位于时间戳 1 处(即 "bar") 。
timeMap.set("foo", "bar2", 4); // 存储键 "foo" 和值 "bar2" ,时间戳 timestamp = 4  
timeMap.get("foo", 4);         // 返回 "bar2"
timeMap.get("foo", 5);         // 返回 "bar2"

提示:

  • 1 <= key.length, value.length <= 100
  • keyvalue 由小写英文字母和数字组成
  • 1 <= timestamp <= 107
  • set 操作中的时间戳 timestamp 都是严格递增的
  • 最多调用 setget 操作 2 * 105

解题思路:

  1. 使用 Map 来存储键以及与其相关联的时间戳-值对列表。
  2. set 方法:在指定时间戳下向列表中添加新的值。
  3. get 方法:使用二分查找在给定时间戳下获取键的最新值。

JavaScript代码实现:

var TimeMap = function() {
    this.map = new Map(); // 创建一个新的 Map 用来存储键和其时间戳-值对的列表
};

TimeMap.prototype.set = function(key, value, timestamp) {
    if (!this.map.has(key)) {
        this.map.set(key, []); // 如果键不存在,则创建一个新的列表
    }
    this.map.get(key).push([timestamp, value]); // 向键的列表中添加新的时间戳和值
};

TimeMap.prototype.get = function(key, timestamp) {
    const list = this.map.get(key); // 获取键的列表
    if (!list) return ""; // 如果键不存在,返回空字符串

    let left = 0; // 定义搜索范围的左边界
    let right = list.length - 1; // 定义搜索范围的右边界

    // 二分查找,直到 left 大于 right
    while (left <= right) {
        const mid = Math.floor((left + right) / 2); // 计算中间位置
        const [ts, val] = list[mid]; // 获取中间位置的时间戳和值

        if (ts === timestamp) { // 如果找到精确匹配的时间戳,直接返回对应的值
            return val;
        } else if (ts < timestamp) { // 如果时间戳小于目标时间戳,则向右搜索
            left = mid + 1;
        } else { // 如果时间戳大于目标时间戳,则向左搜索
            right = mid - 1;
        }
    }

    // 当 left > right 时,right 指向了最后一个时间戳小于等于目标时间戳的元素
    return list[right] ? list[right][1] : ""; // 返回最近的时间戳对应的值,若没有则返回空字符串
};
转载自:https://juejin.cn/post/7421024333243613193
评论
请登录