981. Time Based Key-Value Store

Create a timebased key-value store class TimeMap, that supports two operations.

  1. set(string key, string value, int timestamp)

Stores the key and value, along with the given timestamp.
2. get(string key, int timestamp)

Returns a value such that set(key, value, timestamp_prev) was called previously, with timestamp_prev <= timestamp.
If there are multiple such values, it returns the one with the largest timestamp_prev.
If there are no values, it returns the empty string ("").

Example 1:

Input: inputs = ["TimeMap","set","get","get","set","get","get"], inputs = [[],["foo","bar",1],["foo",1],["foo",3],["foo","bar2",4],["foo",4],["foo",5]]
Output: [null,null,"bar","bar",null,"bar2","bar2"]

Explanation:   
TimeMap kv;   
kv.set("foo", "bar", 1); // store the key "foo" and value "bar" along with timestamp = 1   
kv.get("foo", 1);  // output "bar"   
kv.get("foo", 3); // output "bar" since there is no value corresponding to foo at timestamp 3 and timestamp 2, then the only value is at timestamp 1 ie "bar"   
kv.set("foo", "bar2", 4);   
kv.get("foo", 4); // output "bar2"   
kv.get("foo", 5); //output "bar2"   

Example 2:

Input: inputs = ["TimeMap","set","set","get","get","get","get","get"], inputs = [[],["love","high",10],["love","low",20],["love",5],["love",10],["love",15],["love",20],["love",25]]
Output: [null,null,null,"","high","high","low","low"]

Note:

All key/value strings are lowercase.
All key/value strings have length in the range [1, 100]
The timestamps for all TimeMap.set operations are strictly increasing.
1 <= timestamp <= 10^7
TimeMap.set and TimeMap.get functions will be called a total of 120000 times (combined) per test case.

方法1: hash + binary search (map + vector)

思路:
张慕晖: https://zhanghuimeng.github.io/post/leetcode-981-time-based-key-value-store/

binary search 模版中的“最后一个小于等于”。注意OJ这里有一个巨大的test case,中间用一个变量nums存储hash[key]都会TLE。

易错点

  1. 最后往“最后一个小于等于”转化时,需要谨慎:先判断如果全都不满足,返回最后一个;如果left满足,且不为第一个元素,向前取一个转化回“最后一个小于等于”;否则left == 0, 全都大于,返回空。
  2. 一开始就要查空,因为后面一定会用到index = 0
  3. if (hash[key][0].first > timestamp) return “”:意在加速,好像没用
class TimeMap {
public:
    /** Initialize your data structure here. */
    TimeMap() {
        
    }
    
    void set(string key, string value, int timestamp) {
        hash[key].emplace_back(make_pair(timestamp, value));
        //hash[key].emplace_back({timestamp, value});
        //hash[key].insert({timestamp,value});
    }
    
    // 目标是找到“最后一个小于等于”
    // 转换成“第一个大于”,最后取之前一个
    string get(string key, int timestamp) {
        if (hash.count(key) == 0) return "";
        if (hash[key][0].first > timestamp) return "";
        int left = 0, right = hash[key].size() - 1;
        // auto nums = hash[key]; //  注意nums的类型是pairs
        while (left < right){
            int mid = left + (right - left) / 2;
            if (hash[key][mid].first > timestamp) {
                right = mid;
            }
            else {
                left = mid + 1;
            }
        }
        // 如果全都不满足,返回最后一个
        if (hash[key][left].first <= timestamp)  
            return hash[key].back().second;
        // 如果left满足,且不为第一个元素,向前取一个转化回“最后一个小于等于”
        else if (left > 0)
            return hash[key][left - 1].second;
        // 否则left == 0, 全都大于,返回空
        return "";
    }
private:
    unordered_map<string, vector<pair<int, string>>> hash;
};

/**
 * Your TimeMap object will be instantiated and called as such:
 * TimeMap* obj = new TimeMap();
 * obj->set(key,value,timestamp);
 * string param_2 = obj->get(key,timestamp);
 */

方法2: map + map + upper_bound

论坛上的简洁版:

upper_bound返回第一个大于,exactly是上面二分法寻找的。然后判断边界,取上一个值。比较快。

unordered_map<string, map<int, string>> m;
void set(string key, string value, int timestamp) {
  m[key].insert({ timestamp, value });
}
string get(string key, int timestamp) {
  auto it = m[key].upper_bound(timestamp);
  return it == m[key].begin() ? "" : prev(it)->second;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值