[英]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.