计算嵌套循环的大 O

Posted

技术标签:

【中文标题】计算嵌套循环的大 O【英文标题】:Calculating Big O for nested loops 【发布时间】:2013-10-10 06:53:04 【问题描述】:

我在为以下代码计算大 O 时遇到问题。我从来都不是最聪明的饼干。 有人可以解释一下吗。由于嵌套循环,我的猜测是 O(N^2),但我知道还有更多。

static inline int f1 (int a, int b)

 for (int c = 0; c < b; c++)
 
   a -= n;
 
 return a;


int f2 (int n) 

  int r = n * n * n;
  for (double i = n; i >= 0; i -= 2)
  
     r = f1(r, i);
  
  return r;

【问题讨论】:

O((N/2)^2) 不是一个东西。计算 O 时删除/折叠常量。 我认为没有什么比这更重要的了。我认为计算大 O 表示法非常直观。 【参考方案1】:

首先,请注意 f1 的运行时间完全取决于第二个参数,它控制循环迭代的次数。因此,它的运行时间在第二个参数中是线性的。

接下来,请注意 f2 中的循环运行 n/2 次,其中 i 取值 0、2、4、6、...、n。由于 i 是 f1 的第二个参数,因此运行时间由下式给出

0 + 2+ 4+ ... + n

= 2(0 + 1+ 2+ .. + n)

= 2Θ(n^2)

= Θ(n^2)

所以运行时间是 Θ(n^2)。请注意,几乎所有其他内容都是为了误导您的分心。仅关注控制迭代和循环的变量会揭示您需要关注的实际逻辑。

希望这会有所帮助!

【讨论】:

+1 和第二到第三行是通过意识到 1+2+3+...+n 是 "small gauss" (你用英语叫它吗?)降至 1+2+3+..+n 与 n*(n+1)/2 相同,与 n^2 成比例缩放。【参考方案2】:

    请尝试避免不惜一切代价将 float/double 作为 for 循环计数器,因为它们不精确。使用 size_t 或任何其他 int 类型。此外,据我可以从您的代码中告诉您,无论如何您都将 i 从 double 转换为 int,因此那里不需要那个 double。

    你的循环可以这样写:

    int r = n * n * n;
    for (double i = n; i >= 0; i -= 2)
    
      for (int c = 0; c < i; c++)
      
        r -= n;
      
    
    

外循环:O(n/2) - 每步“跳跃”2 个单位 => 操作数为 n/2

内循环:O(n/2) - 从技术上讲,它迭代到 i,但由于 i 具有 n/2 的最大值并且内循环以 1 乘 1 上升 => 复杂度是相同的 n/2

整体复杂度:O((n/2)^2)

更新

正如其他人所建议的,是的,您可以折叠常量部分(在本例中为“/2”),但在我看来,它更清晰,就像我最初发布的那样。希望这也有帮助。

【讨论】:

【参考方案3】:

从数学上讲,你可以像下面这样正式地进行:

其中 op 是在f1() 中执行的恒定时间op迭代次数。 我可以为f2() 添加op' 或类似的东西,但这似乎没有必要。

要计算操作数,比如 T(10),只需让op = 1

【讨论】:

以上是关于计算嵌套循环的大 O的主要内容,如果未能解决你的问题,请参考以下文章

如何计算嵌套在 for 循环中的 while 循环的时间复杂度?

一般三个嵌套循环的 O(n^3) 复杂度的数学推导

为啥使用 2 个嵌套循环(O(n^2) 复杂度)解决两个和问题,在仅更改循环计数器逻辑时运行得更快?

汽车加油问题(贪心算法),O(n) 复杂度的嵌套 while 循环

带有嵌套 if 语句的 while 循环的 Big-O 运行时

Python中嵌套For循环的时间复杂度