用于查找是否存在"公共号码的算法"

时间:2015-02-16 20:34:13

标签: arrays algorithm data-structures

设一个大小为n的数组。我们需要编写一个算法来检查是否有一个至少出现n/loglogn次的数字。

我已经明白在O(n*logloglogn)中有一种方法可以做到这一点:

  1. 使用选择算法查找中位数并计算它出现的次数。如果它显示超过n/loglogn,我们会返回true。需要O(n)
  2. 根据中位数对数组进行分区。它需要O(n)
  3. 在分区的两侧应用算法(两个n/2数组)。
  4. 如果我们达到的尺寸小于n/loglogn的子阵列,请停止并返回false。
  5. 问题:

    1. 这个算法是否正确?
    2. 重复发生时间为:T(n) = 2T(n/2) + O(n),基本情况为T(n/loglogn) = O(1)。现在,重复树中调用的最大数量是O(logloglogn),并且由于每个调用都是O(n),因此时间复杂度为O(n*logloglogn)。那是对的吗?

1 个答案:

答案 0 :(得分:1)

建议的解决方案有效,复杂性确实是O(n/logloglog(n))

假设“pass i”是深度i的所有递归调用的运行。请注意,每次传递都需要O(n)时间,因为虽然每次调用都远小于O(n),但有几次调用 - 总的来说,每个元素在每个“传递”中处理一次。

现在,我们需要找到传球次数。这是通过求解等式来完成的:

n/log(log(n))  = n / 2^x
<->
n/log(log(n)) * 2^x = n 

这个想法是每次调用都将数组除以一半,直到达到预定义的n/log(log(n))大小。

O(n/log(log(log(n)))中的x确实解决了这个问题,因为you can see in wolfram alpha,因此复杂性确实是O(nlog(log(log(n))))

至于正确性 - 那是因为如果一个元素重复超过要求 - 它必须在一些子数组中,其大小大于/等于所需的大小,并且通过不断减小数组的大小,你将得到一个案例某些地方#repeats <= size(array) <= #repeats - 在这一点上,你将找到这个元素作为中位数,并发现它确实是一个“常用项目”。

O(n/log(log(n))时间内的其他一些方法 - Karp-Papadimitriou-Shanker提出了一些很好的常量,它基于在处理数组时用“候选者”填充表格。