【问题标题】:Why is the bigO of this algorithm m^2*n?为什么这个算法的bigO是m^2*n?
【发布时间】:2014-09-29 19:35:52
【问题描述】:

我试图确定为什么这个算法的 bigO 是 m^2*n,以及为什么最里面的循环以 m^2*n 步执行。

   int m=10, n=15;
   int inLoop = 0, midLoop = 0, outLoop = 0; 

   for(int i=1;i<=m;i++)
   {
    outLoop++; 
        for(int j=1;j<=2*i-1;j++)
        {
            midLoop++; 
            for(int k=1;k<=n;k++)
            {
            inLoop++; 
            }
        }
   }

   System.out.println("Out Loop " + outLoop);
   System.out.println("Mid Loop " + midLoop);
   System.out.println("Inner Loop " + inLoop);

当我运行它时,我得到内部循环运行 1500 次,中间循环运行 100 次,最外面的循环运行 10 次。

在运行这段代码之前,我认为这段代码运行了第一个循环 m 次,第二个循环 m^2 次,最后一个循环 n 次,使用这些值将导致内部循环输出为 15,000。

显然,该算法似乎在 m^2 * n 步骤中执行最内层循环,而不是我认为的 m^3*n 步骤。

【问题讨论】:

  • 为什么中间循环会运行 m^2 次?
  • (2i-1) 当你计算出来时(它是一个总和)结果等于 m^2 次。 @指南针
  • 在运行这段代码之前,我以为这段代码运行了第一个循环 m 次,第二个循环 m^2 次,最后一个循环 n 次 第二个循环或那么这一行中的最后一个循环是不正确的。要么是最后一个循环的 m^2*n,要么是第二个循环的另一个 m。

标签: algorithm big-o


【解决方案1】:

summation(2i - 1) 因为 i 从 1 开始到 m 结束是:

2*summation(i) - summation(1) = 2 * (m+1)/2 * m - m = O(m^2)

这仅适用于外部和中间循环

内部循环直接导致 O(n * m^2)

【讨论】:

  • 那么 m^2 既适用于外循环又适用于中间循环?我认为外部循环运行 m 次,然后中间循环运行 m^2,所以我必须将它们相乘才能得到 m^3 * n。你能再解释一下吗? @Keeto
  • 外循环运行m次,每次外循环运行,中间循环运行(2*i - 1)次,其中i是外循环的迭代次数。
【解决方案2】:

我认为这个想法很清楚,您可以计算每个循环重复的频率,而不清楚的是细节。现在,为了缓解这些事情,您可以将这些循环分开并分别征服它们。

对于最外层的循环,很明显它运行了m 次。也就是说,它的复杂度是 Θ(m x),x 是里面的复杂度。对于最内层的循环,情况也很简单,只取决于n的值,它是常数,所以它的复杂度是Θ(n)。

中间的循环有点复杂。它的复杂度取决于i,但i不是常数而是外循环的循环变量。但是,您可以使用平均值作为替代。在这种情况下,平均值非常简单,如果您绘制棋盘,您可以将其可视化。在外循环的第一次迭代中,i=1,所以j 将只取一个值1。在第二次迭代中,i=2j=1..3。第三个是j=1..5,以此类推。如果你把它们画在下面,你会得到一个三角形的形状。它的顶部宽度为1,底部宽度为2m-1,高度为m。因此它的区域是((2m-1)+1)/2=m

综合起来,外环和中环的复杂度为 Θ(m),内环的复杂度为 Θ(n),总体而言为 Θ(m²n)。

【讨论】:

  • 如果你只运行我上面的代码,你会看到中间的 for 循环输出 100 次,所以我看不出它怎么可能是 m,当它是 100 时m 是 10。仅此一项就表明它不可能是 m
  • 将外循环的十乘以内循环的平均十,就得到了一百。也许还不够清楚,但重点是尽可能单独处理每个循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
  • 2021-11-11
  • 2020-03-21
相关资源
最近更新 更多