设置为添加/删除的平均O(1)和最差/最小O(log n)

时间:2014-01-21 17:24:11

标签: algorithm data-structures

我可以设置一个平均添加/删除操作为O(1)的集合(这对于基于散列表的集合来说是典型的),最差的最大/最小值小于O(n),可能是O(log n)(典型的对于基于树的集合)?

upd 嗯,在最简单的情况下,我可以在每次最大/最小消失时重新扫描所有N个元素,通常它会给我O(1)。但是我将我的算法应用于股票交易,其中最接近/最大值的变化更有可能,所以我只是不想每次最大或最小消失时重新扫描所有内容,我需要比完全重新扫描更聪明的东西,它给出O(n)。< / p>

upd2 在我的案例中,包含100-300个元素。最大/最小元素的变化很可能,因此max / min经常变化。我需要跟踪最大/分钟。我仍然想要添加/删除O(1)。

2 个答案:

答案 0 :(得分:6)

这是一个不可能的结果,在一个确定性模型中最坏情况,非摊销边界的坏常数,其中密钥可以进行比较和散列,但没有别的。 (是的,这是很多规定。我接受了一辆面包车Emde Boas树的推荐。)

通常情况下,比较下限,这是对手的论点。对手的游戏计划是插入许多键,同时有选择地删除算法信息最多的键。最终,算法将无法处理对max()的调用。

对手决定如下关键比对。与每个键相关联的是二进制字符串。每个键最初都有一个空字符串。当比较两个键时,它们的字符串被最小化地扩展,使得它们都不是另一个的前缀,并且根据字典顺序来确定比较。例如,使用键x,y,z,我们可以:

x < y:  string(x) is now 0, string(y) is now 1
x < z:  string(z) is now 1
y < z:  string(y) is now 10, string(z) is now 11.

设k是一个操作所做的关键比较次数的最坏情况上限。每个密钥比较将总字符串长度增加最多两个,因此对于最多3 * n个插入/删除操作的每个序列,总字符串长度最多为6 * k * n。如果我们在有一个字符串长度至少为6 * k的密钥时插入2 * n个不同的带有散布删除的密钥,那么我们在去往至少有n个密钥的集合的路上最多删除n个密钥,其中每个密钥都有一个字符串短于6 * k位。

将每个键的字符串任意延伸到6 * k位。密钥字符串的(6 * k)位前缀是密钥所属的。目前,该算法没有关于桶内密钥相对顺序的信息。有2 **(6 * k)个桶,我们想象按照(6 * k)位前缀指示的递增顺序从左到右排列。对于足够大的n,存在具有常数(取决于k)键的分数和至少2 * k倍于其右侧的组合桶的密钥的桶。删除后面的键,max()需要一个线性数量的额外比较来整理现在保持最大值的大桶,因为删除完成了所需工作的一半多一点。

答案 1 :(得分:2)

嗯,你知道max/min < CONST,元素都是数字。基于此,您可以获得O(1)插入,O(k+n/k)找到最小/最大 1

有一个大小为k的数组,数组中的每个元素都是一个哈希集。在插入时,将元素插入array[floor((x-MIN)/MAX-MIN)*k)](x = MAX的特殊情况)。假设元素的均匀分布,这意味着每个哈希集具有预期数量的n/k元素。
删除时 - 同样从相关集中删除。

findMax()现在完成如下:找到集合不为空的最大索引 - 它采用O(k)最坏情况,O(n/k)找到第一个非空集合中的最大元素。 / p>

寻找最佳k:

我们需要最小化k + n / k。

d(n+n/k)/dk = 1-n/k^2 = 0
n = k^2
k = sqrt(n)

这使我们O(sqrt(n) + n/sqrt(n)) = O(sqrt(n))平均找到最小/最大值,插入/删除O(1)。

由于最大值和最小值的极端变化,您可能需要“重置”表格,但考虑到“安全边界” - 我相信在大多数情况下这不会成为问题。
每次重置DS时,只需确保你的MAX类似2*max,MIN为1/2*min


(1)假设所有元素都来自已知的分布。在我的回答中,我假设一个统一的分布 - 每个x,y都P(x)=P(y),但是很容易将它修改为任何已知的分布。