是否存在具有以下属性的数据结构:
对于上下文,我将算法问题从编程竞赛减少到:
超过m
个查询,返回尚未返回的k
个最小正数。您可以假设返回的数字小于某个常数n
。
如果上面的数据结构存在,那么您可以在O(m)
时间内执行此操作,方法是创建一个数字1到n
的列表。然后,对于每个查询,找到索引k
处的元素并将其删除。在比赛期间,我的解决方案最终在某些输入上O(m^2)
。
我很确定你可以使用二叉搜索树在O(m log m)
中执行此操作,但我想知道理想的O(m)
是否可以访问。我在网上找到的东西往往很接近,但不是很接近 - 棘手的部分是你删除的元素可以来自列表中的任何地方。
答案 0 :(得分:4)
O(1)
linked list
每个元素都有指向next和previous元素的指针,因此remove只删除元素并设置其邻居的指针,如:
element[ix-1].next=element[ix+1].prev
可以使用O(1)
indexed arrays
中索引处的有序元素
所以你有像dat[]
这样的无序数组和像idx[]
这样的索引数组,元素ix
的访问只是:
dat[idx[ix]]
现在问题是要立即拥有这些属性
你可以尝试将链表与索引数组相关联,但删除需要更新索引表,在最坏的情况下为O(N)
。
如果您只有索引数组,则删除也是O(N)
如果索引采用某种形式的树形结构,则删除可能接近O(log(N))
,但访问权限也大约为O(log(N))
答案 1 :(得分:2)
我相信有一种结构可以在O(n)时间内完成这两个任务,其中n是已被移除的点数,而不是总大小。因此,如果您要删除的数字与数组的大小相比较小,则它接近于O(1)。
基本上,所有数据都存储在一个数组中。已删除元素还有一个优先级队列。初始化如下:
Data = [0, 1, 2, ..., m]
removed = new list
然后,要删除一个元素,可以将它的原始索引(请参见下面的获取方法)添加到优先级队列(按前面最小的元素大小排序),然后保持数组不变。所以删除第3个元素:
Data = [0, 1, 2, 3,..., m]
removed = 2
那么现在是第4名,是第5名:
Data = [0, 1, 2, 3,..., m]
removed = 2 -> 4
然后现在是第3名并且是第4名:
Data = [0, 1, 2, 3,..., m]
removed = 2 -> 3 -> 4
现在要访问一个元素,你可以从它的索引开始。然后,您沿着删除的列表进行迭代,每次将索引增加1,直到您到达的元素大于索引的增加值。这将为您提供您正在寻找的元素的原始索引(即数据中的位置),并且是您需要删除的索引。
这种沿队列迭代的操作有效地将索引增加了被删除之前的元素数量。
对不起,如果我没有很好地解释,我脑子里很清楚,但很难写下来。
评论:
所以这不是OP所期待的,但在适当的情况下可能会很接近。