981-基於時間的鍵值儲存

Null發表於2019-01-19

前言

Weekly Contest 121基於時間的鍵值儲存

建立一個基於時間的鍵值儲存類 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 的那個值。
    • 如果沒有值,則返回空字串("")。

示例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. 所有的鍵/值字串都是小寫的。
  2. 所有的鍵/值字串長度都在 [1, 100] 範圍內。
  3. 所有 TimeMap.set 操作中的時間戳 timestamps 都是嚴格遞增的。
  4. 1 <= timestamp <= 10^7
  5. TimeMap.setTimeMap.get 函式在每個測試用例中將(組合)呼叫總計 120000 次。

解題思路

本題解題前可以去了解一下時序資料庫,本題其實就是實現一個簡單的時序資料庫。同時實現也是很簡單:

  1. 首先定義一個ValueMap,該Maptimestampkey,以valuevalue,這樣就能夠記錄下不同timestamp下的value
  2. 然後再定義一個Map,該Mapkeykey,以ValueMapvalue

需要注意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 "";
        }
    }
}

相關文章