Big o 为什么此代码的运行时为O(n^5)?

Big o 为什么此代码的运行时为O(n^5)?,big-o,time-complexity,Big O,Time Complexity,我被要求确定此代码的大O时间复杂性: function(int n) { for (int i = 0; i < n; i++) { for (int j = i; j < i * i; j++) { if (j % i == 0) { for (int k = 0; k < j; k++) { printf("*"); }

我被要求确定此代码的大O时间复杂性:

function(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < i * i; j++) {
            if (j % i == 0) {
                for (int k = 0; k < j; k++) {
                    printf("*");
                }
            }
        }
    }
}
函数(int n){
对于(int i=0;i

给出的答案是O(n5)。有人能解释为什么,或者如何确定这一点吗?我们是将最内层循环的工作次数相加,还是将每个循环的复杂度相乘?

因此,O时间复杂度是嵌套在任意变量n中的每个循环的最大单个迭代次数的乘积

给你

function (int n) // as in O(n)
{
    for(int i=0;i<n;i++) //  n
    {
    for(int j=i;j<i*i;j++) // n ^ 2
       {

         if(j%i==0) // w/e
           {
             for(int k=0;k<j;k++) // n ^ 2
              {
                printf("*");
              }
            }
       }

     }
}
function(int n)//与O(n)中的一样
{

对于(inti=0;i这样分析代码的一种方法是从最里面的循环开始向外工作

    for (int k=0; k<j; k++)
    {
      printf("*");
    }

从这个角度看,运行时大约接近0.125n4,大约是n4/8。这实际上是有意义的——最内层循环的隐藏常数因子是1/2(因为1+2+3+…+i=i(i+1)/2),最外层循环的隐藏常数因子是1/4(因为13+23+…+n3=n2(n+1)2/4)换句话说,理论与实践非常吻合!

在最坏情况下,该问题总时间复杂度的数学形式如下:

function(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < i * i; j+=i) {
                for (int k = 0; k < j; k++) {
                    printf("*");
                }
        }
    }
}

所以复杂性是O(n^5)

编辑:在上面的回答中,我不注意
如果
性能

我们可以按如下方式更改您的代码:

function(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < i * i; j+=i) {
                for (int k = 0; k < j; k++) {
                    printf("*");
                }
        }
    }
}
函数(int n){
对于(int i=0;i

因此,正如templatetypedef提到的,很明显,总运行时间是
O(n^4)

您可以提供O(n^5)上的源代码吗答案?这是从哪里来的?他们给出了什么解释?这个问题在Narasimha Karumachi的《数据结构和算法变得简单》一书中给出。解释是最外层的循环执行n次,中间的循环执行nxn次,最内层的循环执行nxn次。然后他说总的复杂度是O^5@kpie我以为OP询问代码运行时的大O时间复杂性,因为我不确定他们会谈论什么其他数量。不过,我感兴趣的主要事情是确保我的数学是正确的。你看到任何看起来不对劲的地方吗?据我所知,我可能会离开这里(非常尊重177k和所有)但是O是最坏的情况,就像在没有考虑条件的情况下一样,函数的运行时间是有限的@kpie,而您可以通过将所有循环相乘得到运行时的保守上界,这通常不是确定函数运行时的好方法。您可以得到更精确的上界-这就是我正在尝试的g这里要做的是——通过更仔细地考虑每个循环实际做了多少工作。再一次,我非常确定数学是正确的,这就是为什么我试图了解为什么我得到的答案与OP建议的不同。让我们在聊天中继续这个问题……亲爱的@templatetypedef,这个问题的时间复杂性是
O(n^5)
。您可以看到我的答案。我认为,与前面的答案一样,这忽略了if语句对时间复杂性的影响。我非常确定您有一个不严格的有效答案,而且我编写的程序以经验支持我的数学分析,这一事实让我相信我的答案是正确的。亲爱的@templatetypedef、 你说得对。谢谢你的好意。
#include <iostream>
 #include <cstdint>
 #include <cmath>
 using namespace std;
 
 uint64_t countWork(int n) {
   uint64_t result = 0;
 
   for (int i = 0; i < n; i++) {
     for (int j = 1; j < i * i; j++) {
       if (j % i == 0) {
        for (int k = 0; k < j; k++) {
          result++;
        }
      }
    }
   }
 
   return result;
 }

 int main() {
   for (int n = 100; n <= 1000; n += 100) {
     cout << "Ratio of work to n^4 when n = "
          << n << " is " << countWork(n) / pow(double(n), 4.0) 
          << endl;
   }
 }
Ratio of work to n^4 when n = 100 is 0.120871
Ratio of work to n^4 when n = 200 is 0.122926
Ratio of work to n^4 when n = 300 is 0.123615
Ratio of work to n^4 when n = 400 is 0.123961
Ratio of work to n^4 when n = 500 is 0.124168
Ratio of work to n^4 when n = 600 is 0.124307
Ratio of work to n^4 when n = 700 is 0.124406
Ratio of work to n^4 when n = 800 is 0.12448
Ratio of work to n^4 when n = 900 is 0.124537
Ratio of work to n^4 when n = 1000 is 0.124584
function(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < i * i; j+=i) {
                for (int k = 0; k < j; k++) {
                    printf("*");
                }
        }
    }
}