所有其他答案都是正确的,我只想修改以下内容。我想看看,减少内部k循环的执行量是否足以降低下面的实际复杂度,O(n⁴).
所以我写了以下内容:
for (int n = 1; n < 363; ++n) {
int sum = 0;
for(int i = 1; i < n; ++i) {
for(int j = 1; j < i * i; ++j) {
if(j % i == 0) {
for(int k = 0; k < j; ++k) {
sum++;
}
}
}
}
long cubic = (long) Math.pow(n, 3);
long hypCubic = (long) Math.pow(n, 4);
double relative = (double) (sum / (double) hypCubic);
System.out.println("n = " + n + ": iterations = " + sum +
", n³ = " + cubic + ", n⁴ = " + hypCubic + ", rel = " + relative);
}
执行此操作后,很明显实际上是复杂的n⁴
。输出的最后几行如下所示:
n = 356: iterations = 1989000035, n³ = 45118016, n⁴ = 16062013696, rel = 0.12383254507467704
n = 357: iterations = 2011495675, n³ = 45499293, n⁴ = 16243247601, rel = 0.12383580700180696
n = 358: iterations = 2034181597, n³ = 45882712, n⁴ = 16426010896, rel = 0.12383905075183874
n = 359: iterations = 2057058871, n³ = 46268279, n⁴ = 16610312161, rel = 0.12384227647628734
n = 360: iterations = 2080128570, n³ = 46656000, n⁴ = 16796160000, rel = 0.12384548432498857
n = 361: iterations = 2103391770, n³ = 47045881, n⁴ = 16983563041, rel = 0.12384867444612208
n = 362: iterations = 2126849550, n³ = 47437928, n⁴ = 17172529936, rel = 0.1238518469862343
这表明,n⁴
此代码段的实际和复杂度之间的实际相对差是一个朝0.124...
(大约0.125)附近值渐近的因子。虽然它不能提供确切的价值,但我们可以推断出以下几点:
时间复杂度是您的功能/方法n⁴/8 ~ f(n)
在哪里f
。
- 在Bachmann–Landau表示法家族表中,关于Big O表示法的Wikipedia页上
~
定义了两个操作数边的限制是相等的。要么:
f渐近等于g
(我选择363作为排除的上限,因为这n = 362
是我们得出明智结果的最后一个值。此后,我们超过了长空格,并且相对值变为负数。)
用户kaya3发现了以下内容:
顺便说一下,渐近常数正好是1/8 = 0.125;这是Wolfram Alpha提供的确切公式。
for (j = i; j < i *i; j += i)
则不需要进行模数测试(因为j
保证可以被整除i
)。