这两个嵌套循环真的具有相同的二次时间复杂度吗?

时间:2014-06-03 16:36:15

标签: algorithm time-complexity

以下是我提出的算法的一部分:

for (int i = 0; i < n - 1; i++)
   for (int j = i; j < n; j++)
      (...)

我正在使用这个“双循环”来测试大小为n的数组中所有可能的2元素和。

显然(我必须同意),这个“双循环”是O(n²)

n + (n-1) + (n-2) + ... + 1 = sum from 1 to n = (n (n - 1))/2

这是我感到困惑的地方:

for (int i = 0; i < n; i++)
   for (int j = 0; j < n; j++)
      (...)

第二个“双循环”也具有O(n²)的复杂度,当它明显(最差)比第一个更好(?)时。

我错过了什么?信息准确吗?有人可以解释这个“现象”吗?

5 个答案:

答案 0 :(得分:4)

(n (n - 1))/2简化为n²/2 - n/2。如果对n使用非常大的数字,n/2的增长率与相比会相形见绌,因此为了计算Big-O复杂度,您实际上会忽略它。同样,&#34;常数&#34;当n增加时,1/2的值不会增长,所以你也忽略它。这只会让你

请记住,复杂度计算与&#34;速度&#34;不同。一种算法可能比另一种算法慢五千倍,并且仍具有较小的Big-O复杂度。但是当你将n增加到非常大的数字时,会出现一般模式,通常可以使用简单的公式进行分类:1log nnn log n等等。

创建图表并查看显示的行类型有时会有所帮助:

y=x² y=(x² - x)/2

即使这两个图的缩放系数非常不同,您也可以看到它产生的曲线类型几乎完全相同。

答案 1 :(得分:2)

常数因素。

Big-O表示法忽略常数因子,因此即使第二个循环因常数因子较慢,它们也会以相同的时间复杂度结束。

the definition中,它告诉您可以选择任何旧的常数因子:

  

...当且仅当存在正常数M ...

这是因为我们想要分析算法的增长率 - 常数因素只会使事情复杂化并且通常依赖于系统(操作在不同机器上的持续时间可能不同)。

可以只计算某些类型的操作,但问题就变成了选择哪个操作,以及如果该操作在某些算法中不占主导地位。然后你需要将操作相互关联(以独立于系统的方式,这可能是不可能的),或者你可以为每个操作分配相同的权重,但是这将是相当不准确的,因为一些操作会显着比其他人更长。

O(15n² + 568n + 8 log n + 23 sqrt(n) + 17)(例如)真的有用吗?而不仅仅是O(n²)


(出于以下目的,假设为n >= 2

请注意,我们实际上这里的渐近变小(即,我们接近无穷大)这些术语,但我们总是可以将其简化为常数因素。 (It's n(n+1)/2, not n(n-1)/2

n(n+1)/2 = n²/2 + n/2
       and
n²/2 <= n²/2 + n/2 <= n²

鉴于我们刚刚显示n(n+1)/2位于C.n²D.n²之间,对于两个常数CD,我们&#39 ; ve也刚刚表明它是O(n²)

注意 - big-O表示法实际上严格来说是一个上限(所以我们只关心它比一个函数小,而不是两个之间),但它通常用来表示{{1} (big-Theta),它关心两个边界。

答案 2 :(得分:0)

来自The Big O page on Wikipedia

  

在典型用法中,不使用O表示法的正式定义   直;相反,函数f的O表示法是由   遵循简化规则:
  如果f(x)是几个项的总和,那么   保留增长率最大的一个,其他所有省略

Big-O仅用于给出渐近行为 - 一个比另一个更快进入它 - 它们都是O(N ^ 2)

答案 3 :(得分:0)

你也可以说第一个循环是O(n(n-1)/ 2)。 big-O的奇特数学定义类似于:

如果存在常数c,n,则函数“f”是函数“g”的大-O,使得f(x)< c * g(x)表示某些c和所有x> ñ。

这是一种奇特的方式,说g在某个点上面是一个上限,并且有一些常量应用。然后,O(n(n-1)/ 2)= O((n ^ 2-n)/ 2)是O(n ^ 2)的大O,这对于快速分析来说更加简洁。

答案 4 :(得分:0)

AFAIK,您的第二个代码段

for(int i = 0; i < n; i++) <-- this loop goes for n times
     for(int j = 0; j < n; j++) <-- loop also goes for n times
          (...)

基本上,它的时间复杂度O(n*n) = O(n^2)

根据BIG-O理论,常数因子被忽略,只考虑更高阶。这就是说,如果复杂性为O(n^2+k),那么实际复杂性将O(n^2)常量k将被忽略。

(OR)如果复杂度为O(n^2+n),则实际复杂度为O(n^2),将忽略低阶n

因此,在第一种情况下,复杂度为O(n(n - 1)/2)将/可简化为

O(n^2/2 - n/2) = O(n^2/2) (Ignoring the lower order n/2)
= O(1/2 * n^2)
= O(n^2) (Ignoring the constant factor 1/2)