使用Big-O表示法的数量级

时间:2015-09-02 23:43:25

标签: algorithm big-o magnitude

这很可能已被覆盖,但我还没有找到一个我能够理解的解释。我很快就会感到尴尬。

例如,我试图使用以下的Big-O表示法找到数量级:

count = 0;
for (i = 1; i <= N; i++)
    count++;

我从哪里开始找到定义幅度的内容?我在数学上相对较差,尽管我已经尝试了一些资源,但还没有找到能够解释一段代码转换为代数方程的方法。坦率地说,我甚至无法猜测Big-O效率对于这个循环的影响。

2 个答案:

答案 0 :(得分:2)

您的示例是订单

  

O(N)

其中N=number of elements,并对每个进行了类似的计算,因此

for (int i=0; i < N; i++) {
    // some process performed N times
}

大O符号可能比你想象的要容易;在所有日常代码中,您将找到O(N)在循环中的示例,列表迭代,搜索以及对于每个集合执行一次的任何其他过程。这是首先不熟悉的抽象,O(N)含义&#34;某些工作单元&#34;,重复N次。这个&#34;东西&#34;可以是一个递增计数器,如在您的示例中,或者它可能是冗长和资源密集型计算。在算法设计中,大多数时候“大O”或复杂性比工作单元更重要,这在N变大时尤为重要。描述&#39;限制&#39;或者&#39;渐近&#39;在数学上具有重要意义,它意味着一个较小复杂度的算法将始终击败一个更大的,无论工作单位多么重要,因为N足够大,或者随着N的增长而#34;

另一个例子,了解一般的想法

for (int i=0; i < N; i++) {
   for (int j=0; j < N; j++) {
    // process here NxN times
   }
}

这里的复杂性是

  

O(N 2

例如,如果N = 10,那么第二个&#34;算法&#34;将比第一次长10倍,因为10x10 = 100(=大10倍)。如果你考虑当N等于(比如一百万或十亿)时会发生什么,你应该能够解决它也需要更长的时间。因此,如果你能找到一种在O(N)中做超级计算机在O(N 2 )中做某事的方法,那么你应该能够用旧的x386怀表击败它,或其他旧工具

答案 1 :(得分:2)

这些符号(大O,大欧米茄,theta)简单地说,当事情变得越来越大时,算法将如何“难”(或复杂)渐近。

对于大O,有两个函数:f(x)和g(x)其中f(x)= O(g(x))那么你可以说你能找到一个x从哪个g(x )总是比f(x)大。这就是为什么定义包含“渐近”的原因,因为这两个函数在开始时可能有任何运行(例如f(x)&gt; g(x)少数第一个x)但是从单个点开始,g(x)将得到总是优越的(g(x)> = f(x))。所以你对长期行为感兴趣(不仅仅是小数字)。有时big-O表示法被命名为上限,因为它描述了最糟糕的情况(这个函数永远不会渐近变得更难)。

这是“数学”部分。在练习时,您通常会问:算法需要处理多少次?将完成多少操作?

对于简单的循环,它很容易,因为随着N的增长,算法的复杂性将线性增长(简单的线性函数),因此复杂度为O(N)。对于N = 10,您将不得不进行10次操作,因为N = 100 =&gt; 100次操作,对于N = 1000 =&gt; 1000次操作......所以增长是真正线性的。

我将提供其他一些例子:

for (int i = 0; i < N; i++) {
   if (i == randomNumber()) {
      // do something...
   }
}

这似乎复杂性会降低,因为我将条件添加到循环中,因此我们有可能“做某事”操作的次数会降低。但是我们不知道条件会经过多少次,它可能会每次都经过,所以使用big-O(最坏的情况)我们再次需要说复杂度是O(N)。

另一个例子:

for (int i = 0; i < N; i++) {
   for (int i = 0; i < N; i++) {
       // do something
   }
}

在这里,随着N越来越大,操作数量将会越来越快。 N = 10意味着你必须进行10x10操作,N = 100 =&gt; 100x100次操作,N = 1000 =&gt; 1000x1000次操作。你可以看到增长不再是线性的,它是N x N,所以我们有O(N x N)。

对于最后一个例子,我将使用完整二叉树的想法。希望你知道二叉树是什么。因此,如果您对根有简单的引用并且想要将其遍历到最左侧的叶子(从上到下),那么如果树有N个节点,您需要执行多少操作?该算法类似于:

Node actual = root;
while(actual.left != null) {
   actual = actual.left
}
// in actual we have left-most leaf

你需要做多少次操作(循环执行多长时间)?那取决于树的深度,对吧?如何定义完整二叉树的深度?它类似于log(N) - 以logarithm = 2为基础。所以这里的复杂性将是O(log(N)) - 通常我们不关心对数的基数,我们关心的是函数(线性,二次,logaritmic ......)