包含指数的嵌套循环的时间复杂度是多少?

时间:2019-04-02 09:26:27

标签: c++ math time-complexity

for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; j += pow(i, 2))
        //some O(1) operation

此代码段的时间复杂度是多少? 对于外循环中的每个i,我计算出内循环将执行多少次操作,并发现:

hello

但是我不知道该怎么做... 如果我将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 ...等。

很抱歉再次输入错误的问题...

2 个答案:

答案 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的答案,系列是

enter image description here

其中p是指数。随着x的增长,分数不断缩小,使总和接近固定值(我认为p的小值除外)