题目
题目来源:力扣(LeetCode)
设计一个基于时间的键值数据结构,该结构可以在不同时间戳存储对应同一个键的多个值,并针对特定时间戳检索键对应的值。
实现 TimeMap 类:
TimeMap() 初始化数据结构对象
void set(String key, String value, int timestamp) 存储键 key、值 value,以及给定的时间戳 timestamp。
String get(String key, int timestamp)
返回先前调用 set(key, value, timestamp_prev) 所存储的值,其中 timestamp_prev <= timestamp 。
如果有多个这样的值,则返回对应最大的 timestamp_prev 的那个值。
如果没有值,则返回空字符串(””)。
示例:
输入:["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 = 1timeMap.get("foo", 1); // 返回 "bar"timeMap.get("foo", 3); // 返回 "bar", 因为在时间戳 3 和时间戳 2 处没有对应 "foo" 的值,所以唯一的值位于时间戳 1 处(即 "bar") 。timeMap.set("foo", "bar2", 4); // 存储键 "foo" 和值 "bar2" ,时间戳 timestamp = 4timeMap.get("foo", 4); // 返回 "bar2"timeMap.get("foo", 5); // 返回 "bar2"
思路分析
set 操作:
使用一个哈希表存储 set 操作传入的数据,其中哈希表的键为字符串 key,值为一个二维数组,二维数组中存储的是时间戳 timestamp 和 值 value。
get 操作:
由于 set 操作中的时间戳都是严格递增的,因此二维数组中保存的时间戳也是严格递增的。这样我们就可以根据 get 操作中的 key 在哈希表中找到对应的二维数组 pairs ,然后根据时间戳 timestamp 在 pairs 中二分查找。
我们需要找到最大的不超过 timestamp 的时间戳,对此,我们可以通过二分找到第一个超过 timestamp 的二元组下标 i,若 i > 0 则说明目标二元组存在,即 pairs[i - 1],否则二元组不存在,返回空字符串。
/*** Initialize your data structure here.*/var TimeMap = function () {this.map = new Map();};/*** @param {string} key* @param {string} value* @param {number} timestamp* @return {void}*/TimeMap.prototype.set = function (key, value, timestamp) {this.map.has(key) ? this.map.get(key).push([value, timestamp]) : this.map.set(key, [[value, timestamp]]);};/*** @param {string} key* @param {number} timestamp* @return {string}*/TimeMap.prototype.get = function (key, timestamp) {let pairs = this.map.get(key)if (pairs) {let left = 0, right = pairs.length - 1;while (left <= right) {// 二分// mid = left + right >> 1;let mid = Math.floor((right - left) / 2) + left;if (pairs[mid][1] > timestamp) {right = mid - 1;} else if (pairs[mid][1] < timestamp) {left = mid + 1;} else {return pairs[mid][0];}}// 若 right >= 0 则说明目标二元组存在,即 pairs[i - 1],否则二元组不存在,返回空字符串。return right >= 0 ? pairs[right][0] : ''}return "";};/*** Your TimeMap object will be instantiated and called as such:* var obj = new TimeMap()* obj.set(key,value,timestamp)* var param_2 = obj.get(key,timestamp)*/
