【问题标题】:When do you multiply by the average Big O of nested loop?你什么时候乘以嵌套循环的平均大 O?
【发布时间】:2020-01-23 18:20:53
【问题描述】:

我们什么时候将外循环的大 O 乘以内循环的平均大 O?

for (int i = n; i > 0; i /= 2) {
   for (int j = 0; j < i; j++) {
     //statement
   }
}
Answer: O(n)

在这个问题中,外循环是 O(log n)。由于内部循环根据“i”执行了一定次数,因此采用平均大 O。这导致 n + n/2 + n/4 + ... = 2n 的总和,然后除以得到平均值:O(2n / log n)。

因此 O(log n) * O(2n / log n) = O(n)。

但是为什么我们不需要为这个问题取平均值呢?

for (i = 0; i < n; i++) {
  for (j = 0; j < i * i ; j++){

  }
}
Answer: O(n^3)

外循环是O(n)。内循环是 O(n^2)。但为什么呢?

内循环不是根据外循环中的“i”值执行的吗?那么为什么不像上面的问题那样取平均值呢? - 导致内部循环类似于 O(n^2 / n)。

【问题讨论】:

  • “我们什么时候将外循环的大 O 乘以内循环的平均大 O?” 从不。 “这导致 n + n/2 + n/4 + ... = 2n 的总和” 是的,这是正确的分析。 O(2n) 是 O(n)。
  • @user3386109 “从不”是什么意思?根据定义,平均值是总数除以迭代次数,因此这样做总是正确(但总是不方便)。
  • @kaya3 你回答了你自己的问题。要计算平均值,您首先需要计算总数。总数就是答案。
  • @user3386109 这是假设在不先计算总数的情况下,永远无法计算平均值(或者至少,它的大 O 表示法的顺序)。通常,有;一个明显的例子是for i from 1 to n: for j from 1 to m: ...,其中nm 是独立的常量。另一种常见情况是for i from 1 to n: for j from 1 to i: ...,其中i 的平均值为n/2,因此内部循环平均执行O(n) 次。
  • 不,当平均值计算起来很简单时,总和计算起来同样简单。关键是平均值没有告诉你总数没有告诉你的任何东西。计算平均值永远比计算总数更容易。因此,学生永远不应该计算(或猜测)平均值。

标签: algorithm time-complexity big-o


【解决方案1】:

算法的复杂性是通过计算它在执行时执行的操作数来确定的。对于迭代k 次的循环,其中m 是每次迭代的mean 操作数,执行的操作总数总是 total = k * m,因为平均值是定义为m = total / k

用大 O 表示法这样做也很有意义:如果循环迭代 O(k) 次,并在每次迭代中平均执行 O(m) 操作,则操作总数为 O(k * m)

问题在于,在您的第二个示例中,您没有正确计算平均值。当你说“内循环是O(n^2)”时,这已经是平均值了;您正在考虑外部循环的 一次 迭代的内部循环的迭代次数。总迭代次数为O(n^3),外循环的迭代次数为n,所以均值如预期为O(n^3 / n) = O(n^2)

反过来做这个计算更自然:观察到平均值为O(n^2),外循环迭代O(n)次后,总数为O(n^2 * n) = O(n^3)

【讨论】:

  • 你能解释一下在第一个例子中,2n 是如何在第一个代码 sn-p 中取总数的结果:n + n/2 + n/4 ... 因为它没有乘以外循环的 O(log n)
  • 在您的第一个示例中,您直接计算了总数 - 通过将各个部分相加 - 而不是首先计算平均值。
  • 在第二个例子中,'i' 会随着外部循环的每次迭代而变化。如果 n = 5,则内部循环将运行 0^2 + 1^2 + 2^2 + 3^2 + 4^2 次(30 次)。如果 n = 4,则内部循环将运行 0^2 + 1^2 + 2^2 + 3^2 次(14 次)。这真的是 O(n^2) 吗?
  • 知道i^k 对于i = 1 to n 的平均值是O(n^k) 是一个有用的事实。这可以正式证明,但证明并非微不足道,因此您的直觉是正确的,我们不应该无缘无故地假设它是正确的。
  • @kaya3 证明不只是 (sum_(i=1..n)i^k)/n ≤ (n*n^k)/n = n^k?
猜你喜欢
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多