We want to store values for a key along with timestamps, and when someone asks for a value at a given time, we must return the latest value set at or before that timestamp.
The brute-force idea is:
store everything as-is, and while retrieving, look through all timestamps for that key and pick the best match.
It’s easy to implement, but slow because we scan all timestamps every time we call get().
class TimeMap:
def __init__(self):
self.keyStore = {}
def set(self, key: str, value: str, timestamp: int) -> None:
if key not in self.keyStore:
self.keyStore[key] = {}
if timestamp not in self.keyStore[key]:
self.keyStore[key][timestamp] = []
self.keyStore[key][timestamp].append(value)
def get(self, key: str, timestamp: int) -> str:
if key not in self.keyStore:
return ""
seen = 0
for time in self.keyStore[key]:
if time <= timestamp:
seen = max(seen, time)
return "" if seen == 0 else self.keyStore[key][seen][-1]Where is the total number of unique timestamps associated with a key and is the total number of keys.
For each key, we store all its (timestamp, value) pairs in sorted order by timestamp.
When we call get(key, timestamp), we don’t want to scan everything.
Instead, we want to quickly find the largest timestamp ≤ given timestamp for that key.
Because the timestamps are sorted, we can use binary search to find this position in O(log n) time:
"".So the idea is:
key -> sorted list of (timestamp, value) (or two parallel arrays: one for timestamps, one for values).set(key, value, timestamp):(timestamp, value) into the list for that key, keeping timestamps in sorted order.get(key, timestamp):key does not exist, return "".times be the sorted list of timestamps for this key.times to find the rightmost index i such that times[i] ≤ timestamp.times[i]."" (no value was set at or before that time).from sortedcontainers import SortedDict
class TimeMap:
def __init__(self):
self.m = defaultdict(SortedDict)
def set(self, key: str, value: str, timestamp: int) -> None:
self.m[key][timestamp] = value
def get(self, key: str, timestamp: int) -> str:
if key not in self.m:
return ""
timestamps = self.m[key]
idx = timestamps.bisect_right(timestamp) - 1
if idx >= 0:
closest_time = timestamps.iloc[idx]
return timestamps[closest_time]
return ""Where is the total number of values associated with a key and is the total number of keys.
Each key stores its values in the order they were inserted, and timestamps are guaranteed to be increasing for each key.
This means we can keep a simple list of (value, timestamp) pairs for every key.
To answer a get(key, timestamp) query, we only need to find the latest timestamp that is ≤ the given timestamp.
Because timestamps are sorted, we can use binary search to quickly find this position instead of scanning everything.
This gives an efficient and clean approach:
store values in arrays, then binary-search timestamps when retrieving.
key → list of [value, timestamp]set(key, value, timestamp):[value, timestamp] to the key’s list.get(key, timestamp):"".arr be the list of [value, timestamp] pairs.t ≤ timestamp."".class TimeMap:
def __init__(self):
self.keyStore = {} # key : list of [val, timestamp]
def set(self, key: str, value: str, timestamp: int) -> None:
if key not in self.keyStore:
self.keyStore[key] = []
self.keyStore[key].append([value, timestamp])
def get(self, key: str, timestamp: int) -> str:
res, values = "", self.keyStore.get(key, [])
l, r = 0, len(values) - 1
while l <= r:
m = (l + r) // 2
if values[m][1] <= timestamp:
res = values[m][0]
l = m + 1
else:
r = m - 1
return resWhere is the total number of values associated with a key and is the total number of keys.