【发布时间】:2017-08-08 12:39:30
【问题描述】:
我想实现一个数据结构,为排行榜维护一组S,它可以有效地回答以下查询,同时还可以节省内存:
add(x, t)添加一个得分为x的新项目以设置S和相关时间t。query(u)列出集合S中的前n项目(按分数排序),这些项目与t相关联,因此t + k >= u。每个后续查询的u不小于之前的查询。
在标准英语中,可以单独将高分添加到此排行榜中,我想要一种算法,可以有效地查询帖子k 天(其中k 和@ 987654335@ 是固定常数)。
n 可以假设比项目总数少得多,并且可以假设分数是随机的。
一种简单的算法是在将所有元素添加到按分数排序的平衡二叉搜索树中时存储它们,并在元素超过 k 天时从树中删除它们。检测超过 k 天的元素可以通过另一个按时间排序的平衡二叉搜索树来完成。该算法将产生O(log(h)) 的良好时间复杂度,其中h 是过去k 天添加的分数总数。但是,空间复杂度为O(h),很容易看出,即使接下来的k 天没有添加新分数,大部分保存的数据也不会在查询中报告。
如果n 为1,则只需一个简单的双端队列即可。在将新项目添加到队列的前面之前,请从前面删除分数低于新项目的项目,因为它们永远不会在查询中报告。在查询之前,从队列后面移除太旧的项目,然后返回留在队列后面的项目。所有操作都将摊销恒定的时间复杂度,并且我不会存储永远不会报告的项目。
当n 大于 1 时,我似乎无法制定具有良好时间复杂度且仅存储可能被报告的项目的算法。具有时间复杂度O(log(h)) 的算法会很棒,但n 足够小,所以O(log(h) + n) 也是可以接受的。
有什么想法吗?谢谢!
【问题讨论】:
-
你是否按 t 升序添加项目?
-
大多数时候,但我不想排除网络延迟、需要更新第二台服务器以及其他可能导致不同步的事情的可能性。但如果你有一个算法,只有在你按升序添加项目时才有效,那也很好。
-
一个想法:制作四叉树
-
我们也可以认为k很小吗?
-
@MoTao 我知道这一点,所以我提到分数可能被认为是随机的。虽然最坏情况下的空间复杂度不会小于 O(h),但平均空间复杂度可能会小很多。