题目链接:
981. 基于时间的键值存储
解题思路:
- 本题是一个数据结构的考察题;
- 根据题目中的要求, 自定义的数据结构实质上是维护了一个key-val的键值对组合, 所以可以用Map<key, valu>来储存;
- 同时因为用set设置键值对时, 设置的值同时包含了vlue值和时间戳timestamp, 也即是同一个key, 挂载多个不同的(value+timeStamp)的组合, 所以可以将value值+timeStamp作为一个整体, 自定义一个类Node(否则, 就需要在使用Map<val, timeStamp>的格式作为当前key的value了), 则当前TimeMap维护的数据存储容器的格式为: Map<String, List>;
- 在get()方法中, 需要取得的是当前key下挂载的Node集合中, 不超过给定timestamp的最大t的Node节点, 结合题目中给的set()限制(前后的set()方法传值中timestamp严格递增), 即可将模型简化为:
从属性t递增的List集合中, 查找不超过指定timestamp的最大t的节点, 则可以使用二分查找法找到指定的节点Node.
解题代码:
class TimeMap {
//存储value与时间戳t对应关系
class Node{
public String k;
public String val;
public Integer t;
public Node(String _k, String _v, Integer _t){
this.k = _k;
this.val = _v;
this.t = _t;
}
}
//缓存容器
Map<String, List<Node>> container;
/** Initialize your data structure here. */
public TimeMap() {
this.container = new HashMap<>();
}
//set
public void set(String key, String value, int timestamp) {
List<Node> nodeList = this.container.getOrDefault(key, new ArrayList<Node>());
Node node = new Node(key, value, timestamp);
nodeList.add(node);
this.container.put(key, nodeList);
}
//get
public String get(String key, int timestamp) {
//二分法查找(因为执行set操作是, timeStamp为顺序的)
List<Node> nodeList = this.container.getOrDefault(key, new ArrayList<Node>());
int l = nodeList.size();
if(l == 0){
return "";
}
int start = 0;
int end = l;
while(end > start){
int mid = (end+start)>>1; //此处注意: 使用int mid = (end-start)>>1 +start; [用例4]会超出时间限制
Node curr = nodeList.get(mid);
if(curr.t == timestamp){
return curr.val;
}
if(curr.t > timestamp){ //目标值在左侧
end = mid;
}else{ //目标值在右侧
start = mid+1;
}
}
return start == 0? "" : nodeList.get(start-1).val;
}
}
提交记录[20210710]:
执行用时:145 ms, 在所有 Java 提交中击败了99.64%的用户
内存消耗:114.8 MB, 在所有 Java 提交中击败了5.33%的用户