【问题标题】:I need help understanding how to find the Big-Oh of a code segment我需要帮助了解如何找到代码段的 Big-Oh
【发布时间】:2013-04-29 16:15:23
【问题描述】:

明天是我的计算机科学 II 期末考试,我需要一些帮助来了解如何为代码段找到 Big-Oh。我已经搜索了互联网,但找不到任何我需要如何理解它的示例。

这是我们最终示例中的一个问题:

for(int pass = 1; i <= n; pass++)
{
    for(int index = 0; index < n; index++) 
        for(int count = 1; count < n; count++) 
        {
            //O(1) things here.
        }
    }
}

我们应该找到算法的顺序(Big-Oh)。

认为会是 O(n^3),这就是我得出这个结论的方法

for(int pass = 1; i <= n; pass++) // Evaluates n times
{
    for(int index = 0; index < n; index++) // Evaluates n * (n+1) times
        for(int count = 1; count < n; count++) // Evaluates n * n * (n) times
        {
            //O(1) things here. 
        }
    }
}
// T(n) = (n) + (n^2 + n) + n^3
// T(n) = n^3 + n^2 + 2n
// T(n) <= c*f(x)
// n^3 + n^2 + 2n <= c * (n^3)
// O(n) = n^3

我只是不确定我是否做得正确。有人可以解释如何评估这样的代码和/或确认我的答案吗?

【问题讨论】:

  • 您的答案是正确的,但您计算的每个循环的迭代次数却不是。第一个和第二个都迭代n 次,第三个迭代n - 1 次。显然这不会影响结果。
  • 如果你必须使用 O(n^3) 算法来解决现实世界的问题,情况就很糟糕了。
  • @john: 也取决于很多情况和n 的数量:-)
  • @MM。这就是问题所在,当你的 O(n^3) 代码与 5 个小部件一起工作时,老板很高兴,然后他要求你在 10,000 上运行它。
  • 需要在for(int pass = 1; i &lt;= n; pass++)中定义i。此外,pass 未经过测试。如果 i

标签: c++ algorithm analysis


【解决方案1】:

是的,它是O(n^3)。然而:

for(int pass = 1; pass <= n; pass++) // Evaluates n times
{                 //^^i should be pass

    for(int index = 0; index < n; index++) //Evaluates n times
       for(int count = 1; count < n; count++)  // Evaluates n-1 times
       {
            //O(1) things here. 
       }
    }
}

由于您有三层嵌套 for 循环,嵌套循环将被评估 n *n * (n-1) 次,最内部的 for 循环内的每个操作都需要 O(1) 时间,因此您总共有 n^3 - n^2 常量操作,这是O(n^3) 按增长顺序排列。

可以在此处找到关于如何用大 O 表示法衡量增长顺序的一个很好的总结:

Big O Notation MIT

引用上述文件的部分内容:

嵌套循环

 for I in 1 .. N loop
    for J in 1 .. M loop
      sequence of statements
    end loop;
 end loop;

外循环执行N次。每次外循环执行时,内循环 执行 M 次。结果,内循环中的语句总共执行了 N * M 次。因此,复杂度为 O(N * M)。 在一个常见的特殊情况下,内部循环的停止条件是J &lt;N J &lt;M(即内循环也执行 N 次),两个循环的总复杂度为 O(N^2)。

类似的理由也适用于您的情况。

【讨论】:

  • 好的,那么为什么第二个 for 循环只评估 index &lt; n 条件 n 次?不应该是n + 1,因为它必须评估index = n时的条件,然后停止?
  • @chutch1122 我们计算的是嵌套 for 循环内执行的操作数,而不是评估 for 循环的条件。因此,即使你说的是正确的,但 for 循环的主体只执行了 n 次。
  • @chutch1122 计算循环体的次数,而不是评估index &lt; n 的次数。
  • 你怎么能说 for(int pass = 1; i &lt;= n; pass++) 评估 n 次?我们对i 一无所知。 (请参阅jwpat7 和我的问题。
  • @TonyMorris 很好,我认为它应该通过
【解决方案2】:

你完全正确。你的例子是 O(n^3)。

要找出任何一段代码的 Big Oh 运行时间,您应该考虑这段代码做了多少次 O(1) 事情。

让我简化您的示例以更好地了解这一点:

for(int index = 0; index < n; index++) // Evaluates n * (n+1) times
    for(int count = 1; count < n; count++) // Evaluates n * n * (n) times
    {
        //O(1) things here. 
    }
}

在上述情况下,每次运行外循环,内循环都会运行 n 次。而且你的外循环也运行了 n 次。这意味着你正在做 n 件事, n 次。使它成为 O(n^2)。

另一件需要注意的事情是 Big Oh 是一个上限。这意味着您应该始终考虑当您有大量输入时代码会发生什么(在您的情况下,n 的值很大。这一事实的另一个含义是乘以或添加常量对Big Oh 界。例如:

for(int index = 0; index < n; index++) // Evaluates n * (n+1) times
    for(int count = 1; count < 2*n; count++) // Runs 2*n times
    {
        //O(1) things here. 
    }
}

这段代码的Big Oh运行时间也是O(n^2),因为O(n*(2n)) = O(n^2)。

也可以看看这个:http://ellard.org/dan/www/Q-97/HTML/root/node7.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    相关资源
    最近更新 更多