【问题标题】:Calculating Big O complexity of these algorithms?计算这些算法的大 O 复杂度?
【发布时间】:2017-02-22 19:16:58
【问题描述】:

我正在尝试找出以下 2 种算法的大 O 表示法,但遇到了麻烦。

第一个是:

public static int fragment3 (int n){
int sum = 0;
for (int i = 1; i <= n*n; i *= 4)
  for (int j = 0; j < i*i; j++)
   sum++;
  return sum;
} //end fragment 3

答案应该是O(n^4)。当我尝试自己做时,这就是我得到的: 我查看第一个 for 循环并认为它运行 n^2 logn 次。然后对于内部for循环,它运行n次+外部循环的运行时间n^3 logn次。我知道这是错误的,但就是不明白。

对于下面的代码片段,答案是O(n^9)

public static int fragment6(int n) {
int sum = 0;
for(int i=0; i < n*n*n; i++) {
  if(i%100 == 0) {
    for(int j=0; j < i*i; j += 10)
      sum++;
  } // if
  else {
    for(int k=0; k <= i; k++)
      sum++;
  } // else
 } // outer loop

 return sum;
} // fragment 6

当我尝试它时,我得到:n^3 用于外部 for 循环。对于 if 语句,我得到 n,对于第二个 for 循环,我得到 n + 另一个 for 循环和 if 语句,使其成为 n^5。最后,我在最后的 for 循环中得到 n,所有内容加起来为 O(n^6)

我做错了什么以及获得其O(n^9) 复杂性的正确方法是什么?

【问题讨论】:

    标签: java algorithm structure complexity-theory


    【解决方案1】:

    第一个。

    让我们看看内部循环..

    在外循环的第一次迭代 (i=1) 中,它运行 1 次。在第二次迭代 (i=4) 时,它运行 16 (4*4) 次。在第三次迭代 (i=16) 时,它运行了 256 (16*16) 次。通常,在外循环的第 (k+1) 次迭代中,内循环运行 次,在该迭代中运行为 。所以总迭代次数为

    现在,我们将有多少个数字?为了确定我们应该看看外循环。在其中我增长为,直到达到。所以总的迭代次数是。

    这意味着内循环的总运行次数是

    (从总和中删除除最后一个以外的所有数字)。

    现在我们知道,内部循环至少运行 次,所以我们的速度不会超过 O(n^4)。

    现在,

    求解 N,

    其中 C 是一个常数,所以我们不会比 O(n^4) 慢。

    【讨论】:

      【解决方案2】:

      您计算大 O 的方法完全错误,并且您犯了计算错误。

      在某些常见情况下,您可以采用最坏情况的迭代次数并将它们相乘,但这不是一种可靠的方法,并且在以下情况下会失败:

      for (i = 1; i < n; i *= 2) {
         for (j = 0; j < i; j++) {
            sum++;
         }
      }
      

      这里,外循环运行 log_2(n) 次,内循环最坏情况是 n 次迭代。所以你使用的错误方法会告诉你这段代码的复杂度是 O(n log n)。

      正确的方法是准确计算迭代次数,只在最后进行近似。迭代次数其实是:

      1 + 2 + 4 + 8 + ... + 2^k
      

      其中 2^k 是小于 n 的 2 的最大幂。这个和是 2^(k+1) - 1,小于 2n。所以准确的复杂度是O(n)。

      将此想法应用于您的第一个示例:

      for (int i = 1; i <= n*n; i *= 4)
          for (int j = 0; j < i*i; j++)
              sum++
      

      i 取值4^0, 4^1, 4^2, ..., 4^k,其中4^k 是小于或等于n^2 的4 的最大幂。

      对于给定的i 值,内部循环执行i^2 次。

      所以总的来说,内部sum++ 执行了这么多次:

      (4^0)^2 + (4^1)^2 + ... + (4^k)^2
      = 2^0 + 4^2 + ... + 4^2k
      = 16^0 + 16^1 + ... + 16^k
      = (16^k - 1) / 15
      

      现在根据k 的定义,我们有n^2/4 &lt; 4^k &lt;= n^2。所以n^4/16 &lt; 4^2k &lt;= n^4,由于16^k = 4^2k,我们得到内部循环执行的总次数是O(16^k) = O(n^4)。

      第二个例子可以用类似的方法解决。

      【讨论】:

        【解决方案3】:

        第一种情况:

        • 最后一次运行 i = n^2 的内循环,运行时间为 n^4。外循环最多 n^2,但使用指数增长。对于所有内循环运行的总和,但最后一次小于最后一次运行。所以内循环本质上是贡献了 O(1)。

        第二种情况:

        • 100 % n == 0 在 O 思维中并不重要
        • 其他部分无所谓,比主要部分少很多
        • 外循环从 0 运行到 n^3 => n^3
        • 内循环从 0 运行到 n^6 => n^6
        • 外循环乘以内循环 => n^9

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多