为什么这个算法的Big-O N ^ 2 * log N.

时间:2015-02-18 20:29:32

标签: java algorithm big-o permutation

将数组a从[0]填充到[n-1]:生成随机数,直到得到一个尚未包含在先前索引中的数字。

这是我的实施:

public static int[] first(int n) {
    int[] a = new int[n];
    int count = 0;

    while (count != n) {
        boolean isSame = false;
        int rand = r.nextInt(n) + 1;

        for (int i = 0; i < n; i++) {
            if(a[i] == rand) isSame = true;
        }

        if (isSame == false){
            a[count] = rand;
            count++;
        }
    }

    return a;
}

我认为它是N ^ 2,但它显然是N ^ 2logN,我不确定何时考虑日志功能。

4 个答案:

答案 0 :(得分:34)

立即填写0条目。 1条目的概率1 - 1 / n = (n - 1) / n由随机数填充。因此,我们需要平均n / (n - 1)个随机数来填补第二个位置。一般来说,对于k条目,我们需要平均n / (n - k)个随机数,对于每个数字,我们需要进行k次比较,以检查它是否唯一。

所以我们需要

  

n * 1 /(n - 1)+ n * 2 /(n - 2)+ ... + n *(n - 1)/ 1

平均比较。如果我们考虑总和的右半部分,我们会看到这一半大于

  

n *(n / 2)*(1 /(n / 2)+ 1 /(n / 2 - 1)+ ... + 1/1)

已知分数之和为Θ(log(n)),因为它是harmonic series。所以总和是Ω(n^2*log(n))。以类似的方式,我们可以将总和显示为O(n^2*log(n))。这意味着我们平均需要

  

Θ(n ^ 2 * log(n))

操作。

答案 1 :(得分:14)

这类似于Coupon Collector问题。你从n个项目中挑选,直到你得到一个你还没有的项目。平均而言,您有O(n log n)次尝试(请参阅链接,分析并非易事)。在最坏的情况下,您会检查每次尝试的n个元素。这导致平均复杂度为O(N ^ 2 log N)

答案 2 :(得分:2)

您拥有的算法不是O(n^2 lg n),因为您拥有的算法可能会永远循环而不会完成。想象一下,在你的第一次传球,你得到一些价值$ X $,并在每次后续传球,试图得到第二个值,你继续得到$ X $永远。毕竟,我们在这里谈论最糟糕的情况。这将永远循环。所以,既然你最糟糕的情况永远不会结束,你就无法真正分析。

如果你想知道,如果你知道n总是数组的大小和值的上限,你可以这样做:

int[] vals = new int[n];
for(int i = 0; i < n; i++) {
    vals[i] = i;
}
// fischer yates shuffle
for(int i = n-1; i > 0; i--) {
   int idx = rand.nextInt(i + 1);
   int t = vals[idx];
   vals[idx] = vals[i];
   vals[i] = t;
}

一个循环,一个循环返回。 O(n)。简单。

答案 3 :(得分:-1)

如果我没记错的话,log N部分来自这部分:

for(int i = 0; i < count; i++){
    if(a[i] == rand) isSame = true;
}

请注意,我更改了n的{​​{1}},因为您知道每个循环中的数组中只有count个元素。