我有一个关于复杂性的计算机科学考试,我有这个问题:
int counter = 0;
for (int i = 2; i < n; ++i) {
for (int j = 1; j < n; j = j * i) {
counter++;
}
}
我的解是O(nlogn)因为第一个for
是n-2,第二个for
是以n为底的对数,它是n-2 * logn,也就是O(nlogn)-
但是我的老师告诉我们它是n,当我尝试在cLion中运行它时,它给我2*n,它是O(n),有人能解释为什么它是O(n)吗?
4条答案
按热度按时间qgelzfjb1#
根据经验,您可以看到,对于n=100和n=1,000,这是正确的(大约是系列之和的正确值
如果你想要更多的直觉,你可以考虑这样一个事实,几乎所有的数列,
i > sqrt(2)
。例如如果
n = 100
,则90%的值具有i > 10
,并且对于n = 1,000
,97%的值具有i > 32
。从这一点开始,外循环的所有迭代在内循环中最多有2次迭代(因为根据定义,以
sqrt(n)
为底的log(n)
是2)。如果
n
变得非常大,您还可以应用相同的逻辑来显示从立方根到平方根,log在2和3之间,等等......qacovj5a2#
如果
j
每次迭代都增加i
,而不是乘以i
,那么这将是O(nlogn)。现在,j
循环的增长比n
的增长慢得多,这就是为什么你的老师和CLion说时间复杂度是O(n)。c90pui9n3#
注意,它是
j=j*i
,而不是j=j*2
。这意味着大多数情况下,内部循环只有一次通过。例如,n
为33,当i
在[7,33)中时,内部循环只有一次通过。如果你把上面的图看作一个图形,那么算法的复杂度似乎是O(1/log(n)下的面积),我不知道如何证明,而且计算这个积分涉及到我不熟悉的logarithmic integral function,但是维基百科页面确实说这个函数是O(n/log n)。
让我们做个实验。
x一个一个一个一个x一个一个二个x
所以它是双倍加一点,但是额外的一点会随着
n
的增长而缩小,所以它肯定不是O(n log n),而是O(n/f(n))的形式,其中f()产生某个≥ 1的数,看起来可能是O(n/log n),但这纯粹是推测。无论f(n)是什么,当n趋近无穷大时,O(n/f(n))趋近于O(n),所以我们也称之为O(n)。
dnph8jn44#
对于
i
的某个值,j
将变为因此,内部循环需要执行的次数如下所示
这将导致以下结果:
j < n
。现在考虑
n
作为可以写成m^2
的数,一旦i
达到值m
,所有剩余的内部循环迭代将仅在j
等于1
和j
等于i
时进行(因为i^2将大于n
)。换句话说-将只有2次执行内循环。因此,迭代的总次数为:
再除以
n
,结果是m^2
:给予
第一部分
2 * (1 -1/m)
清除到2,因为m
到无穷大。第二部分是(最坏的情况下):
或
当
log(x)/x
随着x
趋向无穷大而趋向零时,上述表达式也将趋向零。所以完整表达式:
当
m
趋向无穷大时会趋向2。换句话说:总的迭代次数除以
n
将趋向于2,因此我们有O(n)。