前言
Weekly Contest 121的 基於時間的鍵值儲存:
建立一個基於時間的鍵值儲存類
TimeMap
,它支援下面兩個操作:
set(string key, string value, int timestamp)
- 儲存鍵
key
、值value
,以及給定的時間戳timestamp
。
get(string key, int timestamp)
- 返回先前呼叫
set(key, value, timestamp_prev)
所儲存的值,其中timestamp_prev <= timestamp
。- 如果有多個這樣的值,則返回對應最大的
timestamp_prev
的那個值。- 如果沒有值,則返回空字串(
""
)。示例1:
輸入:inputs = ["TimeMap","set","get","get","set","get","get"], inputs = [[],["foo","bar",1],["foo",1],["foo",3],["foo","bar2",4],["foo",4],["foo",5]] 輸出:[null,null,"bar","bar",null,"bar2","bar2"] 解釋: TimeMap kv; kv.set("foo", "bar", 1); // 儲存鍵 "foo" 和值 "bar" 以及時間戳 timestamp = 1 kv.get("foo", 1); // 輸出 "bar" kv.get("foo", 3); // 輸出 "bar" 因為在時間戳 3 和時間戳 2 處沒有對應 "foo" 的值,所以唯一的值位於時間戳 1 處(即 "bar") kv.set("foo", "bar2", 4); kv.get("foo", 4); // 輸出 "bar2" kv.get("foo", 5); // 輸出 "bar2"
示例2:
輸入: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]] 輸出:[null,null,null,"","high","high","low","low"]
提示:
- 所有的鍵/值字串都是小寫的。
- 所有的鍵/值字串長度都在
[1, 100]
範圍內。- 所有 TimeMap.set 操作中的時間戳
timestamps
都是嚴格遞增的。1 <= timestamp <= 10^7
TimeMap.set
和TimeMap.get
函式在每個測試用例中將(組合)呼叫總計 120000 次。
解題思路
本題解題前可以去了解一下時序資料庫,本題其實就是實現一個簡單的時序資料庫。同時實現也是很簡單:
- 首先定義一個
ValueMap
,該Map
以timestamp
為key
,以value
為value
,這樣就能夠記錄下不同timestamp
下的value
。 - 然後再定義一個
Map
,該Map
以key
為key
,以ValueMap
為value
。
需要注意ValueMap
我選擇的是用TreeMap
,其提供firstKey()
能夠快速找到第一個元素,而floorEntry()
則會返回與小於或等於給定鍵的最大鍵關聯的鍵值對映,如果沒有這樣的鍵,則返回null
。
實現程式碼
/**
* 981. 基於時間的鍵值儲存
* @author RJH
* create at 2019-01-27
*/
public class TimeMap {
/**
* 將HashMap和TreeMap組合使用
* 使用TreeMap是因為其能夠有序的儲存資料,因為其提供的firstKey()和floorEntry()很方便
*/
private HashMap<String,TreeMap<Integer,String>> map;
/** Initialize your data structure here. */
public TimeMap() {
map=new HashMap<>();
}
public void set(String key, String value, int timestamp) {
//判斷是否存在這個Key
if(map.containsKey(key)){
TreeMap<Integer,String> valueMap=map.get(key);
//以timpstamp作為key確保記錄不同timestamp下的value
valueMap.put(timestamp,value);
}else{
//初次記錄該key,初始化ValueMap
TreeMap<Integer,String> valueMap=new TreeMap<>();
valueMap.put(timestamp,value);
map.put(key,valueMap);
}
}
public String get(String key, int timestamp) {
if(map.containsKey(key)){
TreeMap<Integer,String> valueMap=map.get(key);
if(valueMap.containsKey(timestamp)){
return valueMap.get(timestamp);
}else{
//需要防止輸入的timestamp比儲存的timestamp都要小的情況
if(timestamp<valueMap.firstKey()){
return "";
}else{
return valueMap.floorEntry(timestamp).getValue();
}
}
}else{
return "";
}
}
}