Introduction Link to heading

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.

Solution Link to heading

Binary Search Solution:

type TimeEntry struct {
    timestamp int
    value string
}

type TimeMap struct {
    store  map[string][]*TimeEntry
}

/** Initialize your data structure here. */
func Constructor() TimeMap {
    return TimeMap{ make(map[string][]*TimeEntry) }
}

func (this *TimeMap) Set(key string, value string, timestamp int)  {
    this.store[key] = append(this.store[key], &TimeEntry{timestamp, value} )
}

func (this *TimeMap) Get(key string, timestamp int) string {
    list := this.store[key]
    n := len(list)
    if n == 0 {
        return ""
    }
    lo, hi := 0, n
    for lo < hi {
        mi := lo + (hi - lo) / 2
        e := list[mi]
        if e.timestamp == timestamp {
            return e.value
        } else if e.timestamp < timestamp {
            lo = mi + 1
        } else {
            hi = mi
        }
    }
    if lo > 0 {
        return list[lo-1].value
    }
    return ""
}


/**
 * Your TimeMap object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Set(key,value,timestamp);
 * param_2 := obj.Get(key,timestamp);
 */

Explanation Link to heading

Lets use the fact that all entries are adding with strict increasing timestamp, therefore binary search to retrieve the data fits well.