for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; j += pow(i, 2))
//some O(1) operation
此代码段的时间复杂度是多少? 对于外循环中的每个i,我计算出内循环将执行多少次操作,并发现:
但是我不知道该怎么做... 如果我将pow部分更改为pow(i,3)或更高的功率怎么办?
感谢您的帮助!
编辑:对不起,但我想我想问一下
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; j *= i)
//some O(1) operation
以更高的功率表示j * =(i * i)或j * = i * i * i ...等。
很抱歉再次输入错误的问题...
答案 0 :(得分:3)
如果我正确理解了您的代码,则不应该涉及对数。步骤总数应为
n + n/2 + n/2^2 + n/3^2 + ...
这是一个几何级数。总计为2n。
编辑: 正如评论中指出的那样,它不是几何的。正确的总和为pi ^ 2/6 * n,请参见https://en.wikipedia.org/wiki/Basel_problem。但是仍然是O(n)。
答案 1 :(得分:3)
如@paragon所示,复杂度为O(n)
。此外,有时只需简单地计算发生的迭代次数通常就会显示出复杂性:
#include <iostream>
unsigned f(unsigned n) {
unsigned ctr = 0u;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; j += pow(i, 2)) {
++ctr;
}
}
return ctr;
}
int main() {
for (unsigned n = 1u; n < 9u; ++n) {
unsigned a = std::pow(10, n) * 2;
unsigned b = std::pow(10, n);
std::cout << "f(" << a << ") / f(" << b << ") = " << f(a) / static_cast<double>(f(b)) << '\n';
}
}
表明它显然接近O(n)
的复杂性:
f(20) / f(10) = 2.09091
f(200) / f(100) = 2.04016
f(2000) / f(1000) = 2.01001
f(20000) / f(10000) = 2.0035
f(200000) / f(100000) = 2.00105
f(2000000) / f(1000000) = 2.00032
f(20000000) / f(10000000) = 2.0001
f(200000000) / f(100000000) = 2.00003
如果我将pow部分更改为pow(i,3)或更高的功率怎么办?
它将保持不变O(n)
。这是有道理的,因为指数越高,j
越大,完成循环就越早,从而将复杂度降低到i
循环(i <= n
=> O(n)
):
[pow = 1] f(20000000) / f(10000000) = 2.08026
[pow = 2] f(20000000) / f(10000000) = 2.0001
[pow = 3] f(20000000) / f(10000000) = 2.00001
[pow = 4] f(20000000) / f(10000000) = 2
[pow = 5] f(20000000) / f(10000000) = 2
[pow = 6] f(20000000) / f(10000000) = 2
[pow = 7] f(20000000) / f(10000000) = 2
//...
除了@paragon的答案,系列是
其中p
是指数。随着x
的增长,分数不断缩小,使总和接近固定值(我认为p
的小值除外)