大O,总结一系列n个数字的复杂性是多少?

时间:2012-02-12 21:34:21

标签: performance algorithm optimization complexity-theory big-o

我一直以为:

的复杂性

1 + 2 + 3 + ... + n是O(n),并且将两个n乘n矩阵求和为O(n ^ 2)。

但是今天我从教科书中读到“通过前n个整数之和的公式,这是n(n + 1)/ 2”,然后是:(1/2)n ^ 2 +(1 / 2)n,因此O(n ^ 2)。

我在这里缺少什么?

10 个答案:

答案 0 :(得分:17)

big O notation可用于确定任何功能的增长率。

在这种情况下,本书似乎并不是在谈论计算价值的时间复杂性,而是关于价值本身。 n(n+1)/2O(n^2)

答案 1 :(得分:8)

您混淆运行时的复杂性和结果的大小(复杂性)。

求和的运行时间,一个接一个,第一个 n 连续数字确实是 O n )。 1

但结果的复杂性,即“从1到 n ”的大小= n n - 1) / 2是 O n ^ 2)。


1 但是对于任意大的数字,这是简单的,因为添加大数字需要比添加小数字更长的时间。对于精确的运行时分析,您确实必须考虑结果的大小。然而,这通常与编程无关,甚至在纯粹的理论计算机科学中也是如此。在这两个域中,求和数通常被视为 O (1)操作,除非域明确要求(即实现bignum库的操作时)。

答案 2 :(得分:7)

n(n + 1)/ 2是对N个整数的连续序列求和的快速方法(从1开始)。我认为你的算法混淆了一个大哦符号!

如果你认为它是一个函数,那么这个函数的复杂性就是O(1):

public int sum_of_first_n_integers(int n) {
  return (n * (n+1))/2;
}

天真的实现会有很大的O(n)复杂性。

public int sum_of_first_n_integers(int n) {
  int sum = 0;
  for (int i = 1; i <= n; i++) {
    sum += n;
  }
  return sum;
}

即使仅查看单个n×n矩阵的每个单元格也是O(n ^ 2),因为矩阵具有n ^ 2个单元格。

答案 3 :(得分:4)

所以我的猜测是,这实际上是对Cracking the Coding Interview的引用,该段落在StringBuffer实现中:

  

在每个连接上,创建一个新的字符串副本,然后创建   两个字符串被逐个字符地复制。首先   迭代要求我们复制x个字符。第二次迭代   需要复制2x个字符。第三次迭代需要3x,和   等等。因此总时间为O(x + 2x + ... + nx)。这减少了   到O(xn²)。 (为什么不是O(xnⁿ)?因为1 + 2 + ... n等于n(n+1)/2   或者,O(n²)。)

无论出于何种原因,我在第一次阅读中发现这有点令人困惑。需要注意的重要一点是,n正在乘以n,换句话说正在发生,并且占据主导地位。这就是为什么最终O(xn²)只是O(n²) - x有点像红鲱鱼。

答案 4 :(得分:2)

确实没有问题的复杂性,而是算法的复杂性。

在您的情况下,如果您选择迭代所有数字,那么复杂性确实是O(n)

但这不是最有效的算法。更有效的方法是应用公式 - n*(n+1)/2,它是常量,因此复杂度为O(1)

答案 5 :(得分:1)

您的公式不依赖于要添加的数字的数量,因此它是常量时间算法,或O(1)。

如果你一次添加一个数字,那么它确实是O(n)。公式是捷径;这是一种不同的,更有效的算法。当添加的数字全部为1 .. n 时,快捷方式有效。如果你有一个非连续的数字序列,那么快捷方式不起作用,你将不得不回到逐个算法。

但这些都不适用于数字矩阵。要添加两个矩阵,它仍然是O(n ^ 2),因为你要添加n ^ 2个不同的数字对来得到n ^ 2个结果的矩阵。

答案 6 :(得分:0)

对N个任意整数求和和求和N之间存在差异。对于1 + 2 + 3 + 4 + ... + N,您可以利用它们可以被分成具有公共和的对的事实,例如, 1 + N = 2+(N-1)= 3+(N-2)= ... = N + 1.因此,这是N + 1,N / 2次。 (如果有一个奇数,其中一个将被取消配对,但只需稍加努力就可以看到在这种情况下同样的公式。)

但是,这不是O(N ^ 2)。它只是使用 N ^ 2的公式,实际上是O(1)。对于大N,O(N ^ 2)意味着(大致)计算它的步数增加如N ^ 2.在这种情况下,无论N如何,步数都是相同的。

答案 7 :(得分:0)

使用两种方法可以找到n自然系列之和的答案。第一种方法是在循环中添加所有数字。在这种情况下算法是线性的,代码将是这样的

 int sum = 0;
     for (int i = 1; i <= n; i++) {
     sum += n;
   }
 return sum;

类似于1 + 2 + 3 + 4 + ...... + n。在这种情况下,算法的复杂度被计算为执行加法运算的次数,即O(n)。

找到n个自然数的序列之和的答案的第二种方法是最直接的公式n *(n + 1)/ 2。这个公式使用乘法而不是重复加法。乘法运算没有线性时间复杂度。有多种可用于乘法的算法,其时间复杂度范围从O(N ^ 1.45)到O(N ^ 2)。因此,在乘法时间复杂度取决于处理器的架构。但是为了分析目的,乘法的时间复杂度被认为是O(N ^ 2)。因此,当使用第二种方式找到总和时,时间复杂度将为O(N ^ 2)。

这里的乘法运算与加法运算不同。如果有人掌握计算机组织学科的知识,那么他就可以很容易地理解乘法和加法运算的内部工作。乘法电路比加法器电路更复杂,并且需要比加法器电路更高的时间来计算结果。所以系列之和的时间复杂度不能保持不变。

答案 8 :(得分:0)

添加前n个数字:

考虑算法:

Series_Add(n)

   return n*(n+1)/2

该算法确实在 O(| n | ^ 2)中运行,其中| n |是n的长度(位)而不是大小,仅是因为2个数字(k个位之一和另一个l位)的相乘是在 O(k * l)时间内进行的。

小心

考虑此算法:

Series_Add_pseudo(n):
   sum=0   
   for i= 1 to n:
      sum += i
   return sum

这是一种幼稚的方法,您可以假定此算法以线性时间或通常以多项式时间运行。事实并非如此。

n的输入表示(长度)是O(logn)位(除一进制以外的任何n进制编码),并且该算法(尽管其幅度线性地运行)<指数>指数运行输入长度的(2 ^ logn)。 这实际上是伪多项式算法的情况。它似乎是多项式,但不是。

您甚至可以在python(或任何编程语言)中尝试使用中等长度的数字(例如200位)。

应用第一种算法,结果很快就得到了解决,而应用第二种算法,则必须等待一个世纪...

答案 9 :(得分:0)

1 + 2 + 3 + ... + n始终小于n + n + n ... + n次。您可以将此n + n + .. + n重写为n * n。

如果存在一个正整数n0和一个正整数,则

f(n)= O(g(n)) 常数c,使得f(n)≤c * g(n)∀n≥n0

因为Big-Oh代表函数的上限,其中函数f(n)是自然数之和,直到n。

现在,在谈论时间复杂性时,对于少量数字,加法应该是恒定的工作量。但是n的大小可能很大。您不能否认这种可能性。

adding integers can take linear amount of time when n is really large.。因此,您可以说加法是O(n)运算,并且您要添加n个项目。这样就可以使它成为O(n ^ 2)。当然,它并不总是需要n ^ 2的时间,但是当n很大时,这是最坏的情况。 (上限,记得吗?)


现在,假设您直接尝试使用n(n + 1)/ 2来实现它。只是一个乘法和一个除法,这应该是一个常数运算,不是吗? 不。

使用位数的自然大小度量,使用长乘法将两个n位数字相乘的时间复杂度为Θ(n ^ 2)。当用软件实现时,长乘法算法必须处理加法期间的溢出,这可能很昂贵。 Wikipedia

这又使我们变成O(n ^ 2)。