我怎么能找到上面代码的时间复杂度

时间:2016-09-22 10:55:17

标签: algorithm time-complexity nested-loops

 for(i=0; i<n; i++) // time complexity n+1
{
    k=1;   // time complexity n
    while(k<=n) // time complexity n*(n+1)
    {
    for(j=0; j<k; j++) // time complexity ??
     printf("the sum of %d and %d is: %d\n",j,k,j+k); time complexity ??
    k++;
}

上述代码的时间复杂度是多少?我陷入第二个(for),我不知道如何找到时间复杂度,因为j小于k且不小于n。

我总是遇到与时间复杂性有关的问题,你们有一些好文章吗? 特别是关于步数和循环。

3 个答案:

答案 0 :(得分:3)

从问题:

  

因为j小于k且不小于n。

这是完全错误的,我猜这是让你陷入困境的假设。我们知道k可以采取什么价值。在您的代码中,范围从1到n(包括)。因此,如果j小于k,则它也小于n。

来自评论:

  

我知道唯一的输入是n但是在第二个输入中取决于k而不是n。

如果一个变量取决于任何东西,它就在输入上。 j取决于k本身取决于n,这意味着j取决于n

但是,这还不足以推断出复杂性。最后,您需要知道的是printf被调用的次数。

无论如何,外部for循环执行n次。我们可以将其考虑在内。

内部for循环的执行次数取决于k,它在while循环中被修改。我们知道k只需要从1到n的每个值。这意味着内部for循环首先执行一次,然后执行两次,然后执行三次,依此类推,直到n次。

因此,丢弃外部for循环,printf称为1+2+3+...+n次。这笔金额众所周知且易于计算:1+2+3+...+n = n*(n+1)/2 = (n^2 + n)/2

最后,printf的来电总数为n * (n^2 + n)/2 = n^3/2 + n^2/2 = O(n^3)。这是你的时间复杂性。

关于此类代码的最后说明。一旦你看到相同的模式几次,你很快就会开始认识到所涉及的复杂性。然后,当你看到那种带有因变量的嵌套循环时,你会立即知道每个循环的复杂性是线性的。

例如,在下文中,f被称为n*(n+1)*(n+2)/6 = O(n^3)次。

for (i = 1; i <= n; ++i) {
    for (j = 1; j <= i; ++j) {
        for (k = 1; k <= j; ++k) {
             f();
        }
    }
}

答案 1 :(得分:1)

首先,简化代码以显示主循环。所以,我们有一个结构:

for(int i = 0; i < n; i++) {
    for(int k = 1; k <= n; k++) {
        for(int j = 0; j < k; j++) {
        }
    }
}

外循环运行n * n次,但是你对这些信息的处理并不多,因为内循环的复杂性会根据你所在的外循环的迭代而改变,所以它不是就像计算外环运行的次数并乘以其他值一样简单。

相反,我会发现从内循环开始更容易,然后从最内部到最外部添加外部循环。

  • 最内层循环的复杂性为k

  • 使用中间循环,它是k(上面的复杂度)k = 1 to n的总和。所以1 + 2 + ... + n = (n^2 + n) / 2

  • 使用外部循环,它完成了n次,因此再次乘以n。所以n * (n^2 + n) / 2

简化后,我们总共得到O(n^3)

答案 2 :(得分:-1)

上述代码的时间复杂度为:n x n x n = n ^ 3 + 1 + 1 = n ^ 3 + 2,对于3个循环加上两个常数。由于n ^ 3携带最大的生长速率,因此可以忽略常数值,因此时间复杂度将为n ^ 3。

注意:将每个循环作为(n)并获得总时间,每个循环中的多个(n)值。

希望这会有所帮助!