繁体   English   中英

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

[英]Why is the Big-O of this algorithm N^2*log N

将数组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,我不确定何时考虑日志功能。

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))因为它是一个谐波系列 所以总和是Ω(n^2*log(n)) 以类似的方式,我们可以将总和显示为O(n^2*log(n)) 这意味着我们平均需要

Θ(N ^ 2 *的log(n))

操作。

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

你拥有的算法不是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) 简单。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM