我解决了一个有趣的问题,其中对于每个用户,我想保留他最近N天的活动。这可以应用于许多用例,其中一个如此简单:
对于每个用户 - 用户可以随机进入健身房 - 我希望得到他在过去90天内到健身房的总次数。
对我来说这是一个棘手的问题。
我的想法:我想到存储一个向量,其中每个条目将决定一天,然后一个布尔值可能代表他的访问。要计算,只需对数组中该部分进行线性处理就足够了。
最好的方法是什么?
答案 0 :(得分:2)
根据您需要的复杂程度,存储每个客户访问的简单数组应该足够了。
每次访问时,添加一个包含日期/时间的新条目。每天运行检查以查看是否有任何客户端包含超过90天的访问记录。第一条记录不够老意味着没有更多的记录需要检查,因此您可以安全地转移到下一个客户端。
希望这能帮到你!
答案 1 :(得分:1)
你的想法会起作用,但它真的有效地节省空间吗?
你的data-structure将是这样的:一个布尔的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)。