O1时空复杂度的库存统计计算

问题描述

我必须用Java设计一个REST API:-

  1. 使用以下json接受POST请求:-

    { “仪器”:“ ABC”, “ price”:“ 200.90”, “时间戳”:“ 2018-09-25T12:00:00” }

这些记录将保存在内存中,而不是任何类型的数据库中。

  1. 将有一个GET API,该API返回最近60秒内收到的特定仪器记录的统计信息。 GET请求应为:-/ statistics / {instrumentName},例如:-/ statistics / ABC。响应如下所示:-

    { “ count”:“ 3” “ min”:“ 100.00” “ max”:“ 200.00” “ sum”:“ 450.00” “ avg”:“ 150.00” }

  2. 会有另一个GET请求/统计信息,该请求/统计信息返回最近60秒内收到的所有仪器的统计信息(不特定于#2等特定仪器)

该算法实现起来很复杂的原因是应该执行GET调用-O(1)时间和空间复杂度。

我为3#想到的方法是有一个将具有60个存储桶的集合(因为我们必须计算过去60秒的时间,因此每1秒进行一次采样)。每次交易进入时,都会根据密钥(即时分秒)进入特定的存储桶(这将是具有该密钥和该秒的统计信息的映射)。

但是我无法理解的是如何解决2#问题,我们必须在O(1)的时间和空间复杂度中获取特定仪器/ statistics / ABC的最近60秒的统计信息。

清除60秒以上的记录的最佳策略是什么?

任何对算法的帮助将不胜感激。

解决方法

将数据存储在Map<String,Instrument>中,并让类看起来像这样:

class Instrument {
    private String name;
    private SortedMap<LocalDateTime,BigDecimal> prices;
    private BigDecimal minPrice;
    private BigDecimal maxPrice;
    private BigDecimal sumPrice;

    // Internal helper method
    private void cleanup() {
        LocalDateTime expireTime = LocalDateTime.now().minusSeconds(60);
        Map<LocalDateTime,BigDecimal> expiredPrices = this.prices.headMap(expireTime);
        for (BigDecimal expiredPrice : expiredPrices.values()) {
            if (this.minPrice.compareTo(expiredPrice) == 0)
                this.minPrice = null;
            if (this.maxPrice.compareTo(expiredPrice) == 0)
                this.maxPrice = null;
            this.sumPrice = this.sumPrice.subtract(expiredPrice);
        }
        expiredPrices.clear(); // Removes expired prices from this.prices
        if (this.minPrice == null && ! this.prices.isEmpty())
            this.minPrice = this.prices.values().stream().min(Comparator.naturalOrder()).get();
        if (this.maxPrice == null && ! this.prices.isEmpty())
            this.maxPrice = this.prices.values().stream().max(Comparator.naturalOrder()).get();
    }

    // other code
}

Instrument的所有公共方法都必须为synchronized,并且必须从对cleanup()的调用开始,因为自从上一次调用以来已经过去了一段时间。 addPrice(LocalDateTime,BigDecimal)方法当然必须更新3个统计信息字段。

要确保统计信息同步,最好有一个Statistics类可用作返回值,因此所有4个主要统计值(包括从{{1 }})代表同一组价格。