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:

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

基于时间的键值存储。创建一个基于时间的键值存储类 TimeMap,它支持下面两个操作:

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

存储键 key、值 value,以及给定的时间戳 timestamp。

2. get(string key, int timestamp)

返回先前调用 set(key, value, timestamp_prev) 所存储的值,其中 timestamp_prev <= timestamp。

如果有多个这样的值,则返回对应最大的  timestamp_prev 的那个值。

如果没有值,则返回空字符串("")。

这个题有两种思路,一是用Java的treemap,另一种是用到binary search。

首先第一种思路,用treemap。因为会存在多个键值是同样的key,但是有不同的value和不同的timestamp,所以一开始比较直观的思路一定是hashmap<String, timestamp>,因为hashmap才能存储类似这种<key, value>键值对的数据。其次,题目要求当找到同样的key,同样的value的时候,要返回最接近timestamp的value,所以想到用treemap<timestamp, String>,因为treemap是可以自动根据key排序的。

时间O(logn) - treemap的get和set都是这个复杂度

空间O(n)

Java实现



1 class TimeMap {
2 private HashMap<String, TreeMap<Integer, String>> map;
3
4 /** Initialize your data structure here. */
5 public TimeMap() {
6 map = new HashMap<>();
7 }
8
9 public void set(String key, String value, int timestamp) {
10 TreeMap<Integer, String> tmap = map.get(key);
11 if (tmap == null) {
12 tmap = new TreeMap<>();
13 map.put(key, tmap);
14 }
15 tmap.put(timestamp, value);
16 }
17
18 public String get(String key, int timestamp) {
19 TreeMap<Integer, String> tmap = map.get(key);
20 if (tmap == null) {
21 return "";
22 }
23 Integer floorKey = tmap.floorKey(timestamp);
24 if (floorKey == null) {
25 return "";
26 }
27 return tmap.get(floorKey);
28 }
29 }
30
31 /**
32 * Your TimeMap object will be instantiated and called as such:
33 * TimeMap obj = new TimeMap();
34 * obj.set(key,value,timestamp);
35 * String param_2 = obj.get(key,timestamp);
36 */


 

第二种思路是用到二分法。在不用treemap的前提下,我们依然需要创建一个hashmap存储key和value(这里会是一个list)的键值对,但是对于value相同但是timestamp不同的数据,我们可以自己创建一个类,把这个类放入list,这样当get key的时候,实际上我们get到的是一个由arraylist串联好的,有相同key的values。当你能得到这个list之后,可以根据给出的变量timestamp找到list中最接近于这个timestamp的键值对。

时间, get - O(1), set - O(logn)

空间O(n)

Java实现



1 class Data {
2 String val;
3 int time;
4
5 Data(String val, int time) {
6 this.val = val;
7 this.time = time;
8 }
9 }
10
11 class TimeMap {
12 Map<String, List<Data>> map;
13
14 /** Initialize your data structure here. */
15 public TimeMap() {
16 map = new HashMap<String, List<Data>>();
17 }
18
19 public void set(String key, String value, int timestamp) {
20 if (!map.containsKey(key)) {
21 map.put(key, new ArrayList<Data>());
22 }
23 map.get(key).add(new Data(value, timestamp));
24 }
25
26 public String get(String key, int timestamp) {
27 if (!map.containsKey(key)) {
28 return "";
29 }
30 return binarySearch(map.get(key), timestamp);
31 }
32
33 private String binarySearch(List<Data> list, int timestamp) {
34 int low = 0;
35 int high = list.size() - 1;
36 while (low < high) {
37 int mid = (low + high) / 2;
38 if (list.get(mid).time == timestamp) {
39 return list.get(mid).val;
40 }
41 if (list.get(mid).time < timestamp) {
42 if (list.get(mid + 1).time > timestamp) {
43 return list.get(mid).val;
44 }
45 low = mid + 1;
46 } else {
47 high = mid - 1;
48 }
49 }
50 return list.get(low).time <= timestamp ? list.get(low).val : "";
51 }
52 }
53
54 /**
55 * Your TimeMap object will be instantiated and called as such:
56 * TimeMap obj = new TimeMap();
57 * obj.set(key,value,timestamp);
58 * String param_2 = obj.get(key,timestamp);
59 */