[Medium] 981. Time Based Key-Value Store
Design a time-based key-value data structure that can store multiple values for the same key at different timestamps and retrieve the key’s value at a certain timestamp.
Implement the TimeMap class:
TimeMap()Initializes the object of the data structure.void set(String key, String value, int timestamp)Stores the keykeywith thevalueat the given timetimestamp.String get(String key, int timestamp)Returns a value such thatsetwas called previously, withtimestamp_prev <= timestamp. If there are multiple such values, it returns the value associated with the largesttimestamp_prev. If there are no values, it returns"".
Examples
Example 1:
Input
["TimeMap", "set", "get", "get", "set", "get", "get"]
[[], ["foo", "bar", 1], ["foo", 1], ["foo", 3], ["foo", "bar2", 4], ["foo", 4], ["foo", 5]]
Output
[null, null, "bar", "bar", null, "bar2", "bar2"]
Explanation
TimeMap timeMap = new TimeMap();
timeMap.set("foo", "bar", 1); // store the key "foo" and value "bar" along with timestamp = 1.
timeMap.get("foo", 1); // return "bar"
timeMap.get("foo", 3); // return "bar", since there is no value corresponding to foo at timestamp 3 and timestamp 2, then the only value is at timestamp 1 is "bar".
timeMap.set("foo", "bar2", 4); // store the key "foo" and value "bar2" along with timestamp = 4.
timeMap.get("foo", 4); // return "bar2"
timeMap.get("foo", 5); // return "bar2"
Example 2:
Input
["TimeMap", "set", "set", "get", "get", "get", "get", "get"]
[[], ["love", "high", 10], ["love", "low", 20], ["love", 5], ["love", 10], ["love", 10], ["love", 15], ["love", 20], ["love", 25]]
Output
[null, null, null, "", "high", "high", "low", "low", "low"]
Explanation
TimeMap timeMap = new TimeMap();
timeMap.set("love", "high", 10);
timeMap.set("love", "low", 20);
timeMap.get("love", 5); // return "" (no value at timestamp <= 5)
timeMap.get("love", 10); // return "high"
timeMap.get("love", 10); // return "high"
timeMap.get("love", 15); // return "high" (closest timestamp <= 15 is 10)
timeMap.get("love", 20); // return "low"
timeMap.get("love", 25); // return "low"
Constraints
1 <= key.length, value.length <= 100keyandvalueconsist of lowercase English letters and digits.1 <= timestamp <= 10^7- All the timestamps
timestampofsetare strictly increasing. - At most
2 * 10^5calls will be made tosetandget.
Thinking Process
- Strictly Increasing Timestamps: The guarantee that timestamps are strictly increasing means we don’t need to sort - values are automatically in sorted order
lower_bound: Finds first position wheretimestamp >= target, then check previous elementupper_bound: Finds first position wheretimestamp > target, previous element is always the answerupper_boundis slightly simpler as it doesn’t require checking for exact match
- The search space must shrink monotonically each step.
- Decide which half still satisfies the predicate, discard the other.
- Use
mid = left + (right - left) / 2to avoid overflow.
Common Approaches
Typical techniques for this pattern:
| Approach | Time | Space | Notes |
|---|---|---|---|
| Standard binary search (this problem) | O(log n) | O(1) | Sorted array, left <= right |
| Lower / upper bound | O(log n) | O(1) | First/last position, insert index |
| Binary search on rotated array | O(log n) | O(1) | Identify sorted half, discard other |
| Binary search on answer | O(n log M) | O(1) | Monotonic predicate over search space |
Solution
class TimeMap {
public:
TimeMap() {
}
void set(string key, string value, int timestamp) {
cache[key].emplace_back(timestamp, value);
}
string get(string key, int timestamp) {
if(!cache.contains(key)) return "";
string rtn = "";
const auto& values = cache[key];
int left = 0, right = values.size();
while(left < right) {
int mid = left + (right - left) / 2;
if(values[mid].first <= timestamp) {
rtn = values[mid].second;
left = mid + 1; //search right for newer valid timestamp
} else {
right = mid;
}
}
return rtn;
}
private:
unordered_map<string, vector<pair<int, string>>> cache;
};
Solution Explanation
Approach: Standard binary search (this problem)
Key idea: 1. Strictly Increasing Timestamps: The guarantee that timestamps are strictly increasing means we don’t need to sort - values are automatically in sorted order
How the code works:
- Strictly Increasing Timestamps: The guarantee that timestamps are strictly increasing means we don’t need to sort - values are automatically in sorted order
lower_bound: Finds first position wheretimestamp >= target, then check previous elementupper_bound: Finds first position wheretimestamp > target, previous element is always the answerupper_boundis slightly simpler as it doesn’t require checking for exact match- The search space must shrink monotonically each step.
- Decide which half still satisfies the predicate, discard the other.
Time: - set: O(1) amortized - appending to vector · Space: O(n) - storing all key-value pairs with timestamps
Related Problems
- 34. Find First and Last Position of Element in Sorted Array - Binary search with lower/upper bounds
- 35. Search Insert Position - Lower bound binary search
- 146. LRU Cache - Another design problem with time-based operations
- 729. My Calendar I - Interval-based design problem
Common Mistakes
- Skipping edge cases (empty input, single element, boundaries).
- Off-by-one errors in loops and index ranges.
- Forgetting to handle the case when no valid answer exists.
Key Takeaways
- Strictly Increasing Timestamps: The guarantee that timestamps are strictly increasing means we don’t need to sort - values are automatically in sorted order
- Binary Search Pattern: Finding the largest timestamp <= target is a variant of binary search
- Rightmost Valid Element: We need the rightmost position where
timestamp <= target_timestamp - STL Alternatives:
lower_bound: Finds first position wheretimestamp >= target, then check previous elementupper_bound: Finds first position wheretimestamp > target, previous element is always the answerupper_boundis slightly simpler as it doesn’t require checking for exact match
References
- LC 981: Time Based Key-Value Store on LeetCode
- LeetCode Discuss — LC 981: Time Based Key-Value Store
- LeetCode Editorial (may require premium)