简体   繁体   中英

What would be the time complexity for nested loops containing exponential?

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

What would be the time complexity for this snippet? For each i in the outer loop, I calculate the how many operations the inner loop will perform, and found:

你好

But I don't know how to do the math... And what if I change the pow part to pow(i, 3) or higher power?

Any help is appreciated!

edit: sorry, but I figured I was trying to ask

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

And by higher power, I mean j *= (i * i) or j *= i * i * i... and so on.

Sorry again for the wrong question...

If I am understanding your code correctly, there shouldn't be logarithms involved. The total number of steps should be

n + n/2 + n/2^2 + n/3^2 + ...

This is a geometric series. It sums to 2n.

EDIT: As pointed out in the comments, it is not geometric. The correct sum is pi^2/6*n, see https://en.wikipedia.org/wiki/Basel_problem . But still is is O(n).

The complexity is O(n) as @paragon showed. Also, sometimes simply counting how many iterations occour will often reveal the complexity:

#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';
    }
}

showing that it clearly approaches a O(n) complexity:

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

And what if I change the pow part to pow(i, 3) or higher power?

it will stay still be O(n) . It makes sense, because the higher the exponent, the larger j grows completing its loop even earlier reducing the complexity to the that of the i loop ( 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
//...

adding to @paragon's answer, the series is

在此处输入图片说明

where p is the exponent. As x grows, the fraction shrinks making the sum approach a fixed value (except for small values of p I think)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM