【问题标题】:Why is the complexity of the following nested loop O(n√n)?为什么以下嵌套循环的复杂度为 O(n√n)?
【发布时间】:2013-11-17 10:50:20
【问题描述】:

我无法弄清楚以下代码的复杂性。虽然,我知道正确的答案。只是想知道为什么会这样。

void main()
{
    int i, j, n, x;
    for(i=0; i < n; i++)
    {
        for(j=0; j*j <= n; j++)
        {
           x=10;
        }
    }
}

复杂度为 O(n√n)。

【问题讨论】:

  • 如果我们忽略 n 没有初始化为一个值。由于 x 总是变成 10,一个好的编译器会直接删除循环并将 x 设置为 10,因此没有复杂性。
  • @Johan Emmm.... 没有“没有复杂性”这样的东西。它被称为 O(1)
  • @Johan 如果使用-O0 执行,即使是好的编译器也不应该这样做:-)
  • 甚至不需要分配x,因为它是一个局部变量。该程序没有明显的副作用。

标签: c for-loop


【解决方案1】:

外部循环执行n 迭代。

内部循环执行sqrt(n) 迭代(因为它将j 平方n 进行比较)。

循环体花费恒定的时间。

将这三个相乘得到O(n sqrt(n))

附:一个好的编译器可能会为这个精确的循环生成O(1) 代码。

【讨论】:

  • 你如何在这里总结sqrt(n)?两个循环都从 0 运行到 n 并且 n 未被修改。
  • @Wolph:终端条件不同(一个使用i,另一个使用j的平方)。
【解决方案2】:

第一个循环可以从 1 转到 n,第二个循环将从 1 转到 sqrt(n) .. 这就是复杂度为 O(n*sqrt(n)) 的原因。

【讨论】:

    【解决方案3】:

    外部循环是 O(n) - 执行时间与元素数量成正比。

    但它有一个内循环,每次外循环迭代执行一次。当执行次数或执行次数的平方等于 n 时,此操作停止。也就是说,外循环的每次迭代都执行√n次。

    因此总复杂度为 O(n x √n),写为 O(n√n)。

    【讨论】:

      【解决方案4】:

      画一张表格,你就会知道为什么。假设n = 10

        i  |  j  
      -----+-----
        0  |  0   0*0 <= 10 ? Yes  |                |
        0  |  1   1*1 <= 10 ? Yes  |                | 
        0  |  2   2*2 <= 10 ? Yes  | → O(√n) Times  |
        0  |  3   3*3 <= 10 ? Yes  |                | 
        0  |  4   4*4 <= 10 ? NO!  |                |
        1  |  0   ...                               | 
        1  |  1                                     | → O(n) Times
        .. | ..                                     |
        .. | ..                                     |
        9  |  0                                     |
        9  |  1                                     |
        9  |  2                                     |
        9  |  3                                     |
        9  |  4                                     |
      

      现在您观察到内部循环执行 O(√n) 次。外循环很简单,它需要 O(n)。将它们相乘得到你得到的结果。

      【讨论】:

      • 您从哪里获得4*4 &lt;= 10?那不在我看到的代码中?我错过了编辑吗?
      • @Wolph 为了示例,我将 n 固定为 10。
      • @Wolph 我认为这可能有助于 OP 更好地理解流程:)
      【解决方案5】:

      使用 Sigma 表示法,您可以获得准确的迭代次数加上增长复杂度的顺序(经验验证):

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-11
        • 2018-01-14
        • 2020-06-25
        • 2018-11-26
        相关资源
        最近更新 更多