【问题标题】:C loop complexityC 循环复杂度
【发布时间】:2013-01-08 12:39:06
【问题描述】:

我正在准备考试,这些是去年考试中的一些问题。任务是计算精确复杂度和渐近复杂度。你会怎么解决?如果可能,普遍使用。

for ( i = j = 0; i < n; j ++ ) {
  doSomething ();
  i += j / n;
  j %= n;
}

for ( i = 0; i < 2 * n; i += 2 )
  for ( j = 1; j <= n; j <<= 1 )
    if ( j & i )
      doSomething ();

for (i = 0; i < 2*n; i++) {
  if ( i > n )
    for (j = i; j < 2 * i; j ++ ) doSomething();
  else
    for (j = n; j < 2 * n; j ++ ) doSomething();
}

提前致谢

【问题讨论】:

  • 我不明白第一个的意思。好吧,就像for (0 to 199) { for (0 to 200) { /* .. */ } },但是.. 好吧,不
  • 意义在于测试我们的 C 和算法知识。您能解释一下您是如何得出结果的吗?
  • 忘了补充,我将n 定义为200

标签: c loops complexity-theory asymptotic-complexity


【解决方案1】:

我对第三个循环的解决方案是

t(n) = [ (n-1)*n +  ((n-1)*n)/2 ] *D  + [ n^2 +n ] *D + [ 2n ]*I

所以它在O(n^2) 中,因为doSomething() 有一个恒定的时间 并且ij 是整数。

第二个词([ n^2 +n ] *D)相当简单。

循环

for (j = n; j < 2 * n; j ++ ) doSomething();

i &lt;= n 时被调用,因此它将被调用 n+1 次,因为它从 0 开始。

循环for (j = n; j &lt; 2 * n; j ++ ) 调用doSomething() n 次,所以我们有(n+1)*n*D = [n^2+n] *D。我假设doSomething() 的时间恒定,等于D

第一项有点复杂。

for (j = i; j < 2 * i; j ++ ) doSomething();

i&gt;n 时被调用,因此它将被调用n-1 次。 循环调用doSomething() i 次。 第一次调用n+1,第二次调用'n+2',以此类推,直到它是2n-1,等于n + (n-1)。 所以我们得到一个像这样的序列{n+1, n+2, n+3, ... , n+(n-1)}

如果我们对序列求和,我们得到n-1 乘以n 和总和1+2+3+...+ (n-1)。 最后一项可以用"Gaußsche Summenformel"解决(对不起,我没有它的英文名称,但你可以在德语维基链接中看到公式)所以它等于((n-1)*n)/2

所以第一个词是(n-1) * n + ((n-1)*n)/2 *D

最后一项是 if 语句,称为2*n*I,其中I 是执行 If 语句的时间。

【讨论】:

    【解决方案2】:

    好吧,这里的问题是,对于所有三个循环结构,迭代量如何与n 成比例变化,对吧?所以让我们看看循环。我将省略第一个,因为你已经解决了。

    for ( i = 0; i < 2 * n; i += 2 )
      for ( j = 1; j <= n; j <<= 1 )
        if ( j & i )
          doSomething ();
    

    显然,外部 for 循环恰好运行 n 次。由于按位移位操作,内部循环运行log_2(n) 次。 if 子句在恒定时间内运行,因此整个循环在 O(n * log_2(n)) 中,假设 doSomething() 也在恒定时间内。

    这样会更清楚吗? :)

    【讨论】:

    • 您能否进一步解释一下您是如何计算内循环的?
    • @Grant 你知道&lt;&lt;= 运算符吗?你知道 log_2(n) 大致近似于表示 n 所需的位数吗?
    • 谢谢,我现在知道了。我不知道 log_2(n)。
    【解决方案3】:

    根据要求,我将解释我是如何得出第一个循环等于这样的结构的结果:

    int i, j;
    for (i=0; i < n; i++) {
        for (j=0; j <= n; j++) {
            doSomething();
        }
    }
    

    首先,我必须承认,在我真正考虑之前,我只是编写了一个小示例程序,包括三个 for 循环中的第一个,在迭代期间打印出 ij。看到结果后,我在想为什么结果是这样的。

    在评论中,我忘记添加我定义了n=200

    说明

    我们可以说,虽然j 在迭代中的每一步都会定期递增,但它永远不会超过n 的值。为什么?在n 迭代之后,j==n。它将在 j %= n after i 已递增的语句中设置为 0。在语句i += j / n 中,i 将增加0 n-1 次,在n 次,它将增加1。这一切重新开始,直到i &gt;= n

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 2021-02-18
      • 2013-12-08
      • 1970-01-01
      相关资源
      最近更新 更多