编码:跟踪每个用户的最近N天记录。

时间:2017-05-15 19:50:56

标签: algorithm data-structures array-algorithms

我解决了一个有趣的问题,其中对于每个用户,我想保留他最近N天的活动。这可以应用于许多用例,其中一个如此简单:

对于每个用户 - 用户可以随机进入健身房 - 我希望得到他在过去90天内到健身房的总次数。

对我来说这是一个棘手的问题。

我的想法:我想到存储一个向量,其中每个条目将决定一天,然后一个布尔值可能代表他的访问。要计算,只需对数组中该部分进行线性处理就足够了。

最好的方法是什么?

4 个答案:

答案 0 :(得分:2)

根据您需要的复杂程度,存储每个客户访问的简单数组应该足够了。

每次访问时,添加一个包含日期/时间的新条目。每天运行检查以查看是否有任何客户端包含超过90天的访问记录。第一条记录不够老意味着没有更多的记录需要检查,因此您可以安全地转移到下一个客户端。

希望这能帮到你!

答案 1 :(得分:1)

你的想法会起作用,但它真的有效地节省空间吗?

你的将是这样的:一个布尔的2D向量(你可以将它想象成一个矩阵),其中每一行都是一个用户,每一列都是一天(已排序),所以它包括一个:

  

大小为U x N的矩阵

其中U是用户数。

要回答我最初提出的问题,你需要考虑这个矩阵将如何密集。如果它会变得很多,那么你做出了正确的选择,如果没有,那么你浪费了很多空间。你可以在这里看到权衡。

当然,你必须考虑你的用例。在健身房的例子中,我认为这不会节省空间,因为大多数人每天都不去健身房(我想),这将导致稀疏矩阵,这意味着我们浪费了空间。

另一个想法是使用单个矢量os大小N,其中日期被排序。每个条目都是单个链表,其中每个节点都是用户。

如果在一天的清单中找到了用户,则意味着他当天去了健身房。

通过这种方法,我们可以根据需要为精确分配空间,因此无论我在矩阵的情况下提到的密度如何,它都是最佳空间。

然而,这是吗?不,当然不!我讨论过空间,但时间效率怎么样?例如,搜索是我们希望我们的数据结构支持的常用方法,如果我们希望它快速的话!

在矩阵的情况下,搜索将是一个O(1)操作,这是很好的,因为访问矩阵是一个常量操作。

然而,在vector + list的情况下,搜索将采用O(L),其中L是我们的向量总共具有的列表的平均大小。

那是哪一个?这取决于你的申请!

我也会尝试哈希表,这不需要排序,节省空间(What is the space complexity of a hash table?)。

答案 2 :(得分:1)

为每个客户提供Queue data structu个包含访问日期的元素。 当客户访问健身房时,只需添加当前日期

public getHistory() {

    this.varHistoryService.getHistory(this.selectedConfig.NAME)
        .subscribe(res => {
            this.varTimeSeries = res;
            console.log(this.varTimeSeries);
        },
        errors => {
            console.log(errors);
        });
}.bind(this)

当你需要为他准备一条赛道时:

Q[ClientIdx].Add(Today)

如果标准版本不可用,您可以使用多种语言的标准Queue实现或基于数组/列表的简单实现。

请注意,每个记录都会添加和删除一次,因此每次添加/计数操作的摊销复杂度为O(1)

答案 3 :(得分:0)

为每个用户提供具有固定大小(90)访问详细信息的队列怎么样?您可以为多个用户推广它,关键优势是您不必担心维护最近90天的数据。

您可以将队列转储到列表或数组,并在O(n)中根据需要保留。正如你所提到的,对存在号的检查也是O(n)。