力扣—981. 基于时间的键值存储 ##哈希表+二分存储

题目:创建一个基于时间的键值存储类 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. 所有的键/值字符串都是小写的。
  2. 所有的键/值字符串长度都在 [1, 100] 范围内。
  3. 所有 TimeMap.set 操作中的时间戳timestamps 都是严格递增的。
  4. 1 <= timestamp <= 10^7
  5. TimeMap.set 和 TimeMap.get函数在每个测试用例中将(组合)调用总计 120000 次。

题解:

class TimeMap {
    //内部类
    class Pair implements Comparable<Pair> {
        int timestamp;     //时间戳
        String value;      //值

        public Pair(int timestamp, String value) {
            this.timestamp = timestamp;
            this.value = value;
        }

        public int hashCode() {
            return timestamp + value.hashCode();
        }

        public boolean equals(Object obj) {
            if (obj instanceof Pair) {
                Pair pair2 = (Pair) obj;
                return this.timestamp == pair2.timestamp && this.value.equals(pair2.value);
            }
            return false;
        }

        public int compareTo(Pair pair2) {
            if (this.timestamp != pair2.timestamp) {
                return this.timestamp - pair2.timestamp;
            } else {
                return this.value.compareTo(pair2.value);
            }
        }
    }
    
    //为实现get 操作,用一个哈希表存储set 操作传入的数据
    //哈希表的键为字符串key,值为一个二元组列表,二元组中存储的是时间戳timestamp 和值value。
    Map<String, List<Pair>> map;
    
    public TimeMap() {
        map = new HashMap<String, List<Pair>>();
    }
    
    public void set(String key, String value, int timestamp) {
        List<Pair> pairs = map.getOrDefault(key, new ArrayList<Pair>());
        pairs.add(new Pair(timestamp, value));
        map.put(key, pairs);
    }
    
    public String get(String key, int timestamp) {
        List<Pair> pairs = map.getOrDefault(key, new ArrayList<Pair>());
        // 使用一个大于所有 value 的字符串,以确保在 pairs 中含有 timestamp 的情况下也返回大于 timestamp 的位置
        Pair pair = new Pair(timestamp, String.valueOf((char) 127));
        int i = binarySearch(pairs, pair);
        if (i > 0) {
            return pairs.get(i - 1).value;
        }
        return "";
    }

    private int binarySearch(List<Pair> pairs, Pair target) {
        int low = 0, high = pairs.size() - 1;
        if (high < 0 || pairs.get(high).compareTo(target) <= 0) {
            return high + 1;
        }
        while (low < high) {
            int mid = (high - low) / 2 + low;
            Pair pair = pairs.get(mid);
            if (pair.compareTo(target) <= 0) {
                low = mid + 1;
            } else {
                high = mid;
            }
        }
        return low;
    }
}

复杂度分析

  • 时间复杂度: 初始化 TimeMap 和 set 操作均为O(1); get 操作为 O(logn),其中 n 是set
    操作的次数。最坏情况下set 操作插入的 key 均相同,这种情况下get 中二分查找的次数为 O(logn)。
  • **空间复杂度:**O(n),其中 n 是set 操作的次数。我们需要使用哈希表保存每一次set 操作的信息。

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/time-based-key-value-store/solution/ji-yu-shi-jian-de-jian-zhi-cun-chu-by-le-t98o/
来源:力扣(LeetCode)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值