【问题标题】:Time complexity of a loop increases by log?循环的时间复杂度会增加对数?
【发布时间】:2013-09-06 20:08:47
【问题描述】:

有人可以帮助我了解如何找到以下循环的时间复杂度:

    for (int j = 1 to n) {
      k = j;
       while (k < n) {
        sum += a[k] * b[k];
        k += log n;
       }
     }      

我找到了解决方案here,即 n2 / log(n)。

很明显,外部循环需要 n 次,但对于内部循环,我被卡住了。 n / log n 因子从何而来?

我尝试逐个术语地遵循它,但无法继续

1st time k = 1,
2nd time k = 1 + log n
3rd time k = 1 + log n + log n  //   (2 log n)

stuck here :(

我怎样才能找到一种模式,或者我应该遵循哪些最佳步骤来获得此类代码的时间复杂度?

【问题讨论】:

  • 注意 while() 循环中的k += log n。您可以将其重写为 for (k = j; k &lt; n; k += log n) { ... } 以更明确地说明 O() 中的日志 n 来自何处。
  • 感谢您的解释。其实我可以理解 log 来自哪里,但是为什么 (n/log n) 不能只登录??

标签: algorithm math big-o logarithm


【解决方案1】:

试着这样想:外循环肯定会运行 O(n) 次,所以如果你能确定内循环完成的工作量,你可以将它乘以 O(n) 得到一个上限关于完成的总工作量。

那么让我们看看内部循环。请注意,当循环迭代时,k 将采用值 j、j + log n、j + 2 log n、...、j + i log n,其中i 是循环运行的迭代次数.

所以考虑一下循环可以执行的最大次数。它在 k ≥ n 时立即停止,这意味着它在 j + i log n ≥ n 时立即停止,因此在 (n - j) / log n 次迭代之后,循环将停止运行。如果我们想为这种情况发生的次数获得一个保守的上限,请注意在最坏的情况下我们有 j = 1。这意味着这个循环的最大迭代次数是 (n - 1) / log n = O(n / log n),所以内循环的每次迭代都做 O(n / log n) 的工作。

将每个循环迭代的 O(n / log n) 工作乘以 O(n) 次迭代产生 O(n2 / log n) 的总体结果,这就是期望的结果。

希望这会有所帮助!

【讨论】:

  • 嗯,它确实有很大帮助。一个愚蠢的问题,你为什么要在 lon(n) 上进行除法?直到这一点很清楚。我的意思是在 (n - j) / log 中,是因为增量步骤是 log(n) 吗?非常感谢您的出色而详细的回答
  • @NaifAlghamdi- 由于 k 在迭代 n 中具有值 j + i log n 并且当 k >= n 时循环停止,我们需要确定表达式 j + i 的 i 的最小可能值log n >= n 成立。重新排列,这发生在 i log n >= n - j 时,然后除以 log n 得到 i >= (n - j) / log n。因此,一旦迭代次数 (i) 超过 (n - j) / log n,迭代就会停止。这能更好地解释事情吗?
  • 哇,现在已经很清楚了,经过5天多的尝试,我终于明白了!我真的很感激,templatetypedef。非常感谢。
【解决方案2】:

显然,外部循环按 n 顺序运行。所以问题是:内循环需要多长时间?循环在k &gt;= n 时终止,kj 开始并以log(n) 为步长递增。大约需要

n / log(n)

1nlog(n) 为步长求和的迭代次数(给出或取舍入误差)。但我们并不总是从1 一路走到n - 有时我们从10n,或20,或n/2... 这需要

(n - i) / log(n)

当我们从i而不是1(或0...)开始时,我们可以将内部循环显式执行的总次数写为总和:

total number = sum(i = 1 to n, (n - i) / log(n))
             = sum(i = 1 to n, n / log(n)) - sum( i = 1 to n, i / log(n))

             = O(n * n / log(n)) - something smaller than that.

“较小的术语”大约是第一个术语的一半

sum( i = 1 to n, i ) = n * (n + 1) / 2;

但是当我们查看计算顺序时,这样的常数并不重要 - 我们只想知道当n 变大时会发生什么,所以虽然你可能想说算法运行在O( (1 - 0.5) * n2/log(n)),我们只是说它运行在O( n2/log(n))

现在可以看到了吗?

【讨论】:

  • 很清楚,感谢您的宝贵解释!所以如果增量是以 sqrt(n) 为单位的(例如),那么总数 = sum (i=1 to n; n / sqrt(n),不是吗?
猜你喜欢
  • 2014-04-29
  • 2020-04-01
  • 2021-11-18
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多