# 981 -「java」哈希表内嵌链表 解决『基于时间的键值存储』的详细分析&解题思路

Tags:

  • 中等
  • Map
  • 链表
  • 哈希
  • java

题目链接:

981. 基于时间的键值存储

解题思路:

  1. 本题是一个数据结构的考察题;
  2. 根据题目中的要求, 自定义的数据结构实质上是维护了一个key-val的键值对组合, 所以可以用Map<key, valu>来储存;
  3. 同时因为用set设置键值对时, 设置的值同时包含了vlue值和时间戳timestamp, 也即是同一个key, 挂载多个不同的(value+timeStamp)的组合, 所以可以将value值+timeStamp作为一个整体, 自定义一个类Node(否则, 就需要在使用Map<val, timeStamp>的格式作为当前key的value了), 则当前TimeMap维护的数据存储容器的格式为: Map<String, List>;
  4. 在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%的用户
posted @ 2023-03-20 15:11  zhiyuanZAG  阅读(18)  评论(0)    收藏  举报