c++ - 通过计算步数计算算法复杂度

标签 c++ algorithm data-structures big-o

尝试通过计算步数来计算函数的大 o。我认为这些是如何按照示例中的操作方式来计算每个步骤,但不确定如何计算总数。

int function (int n){
   int count = 0;                              // 1 step
   for (int i = 0; i <= n; i++)                // 1 + 1 + n * (2 steps)
      for (int j = 0; j < n; j++)              // 1 + 1 + n * (2 steps)
         for (int k = 0; k < n; k++)           // 1 + 1 + n * (2 steps)
            for (int m = 0; m <= n; m++)       // 1 + 1 + n * (2 steps)
               count++;                        // 1 step
  return count;                                // 1 step
}

我想说这个函数是 O(n^2),但我不明白它是如何计算的。

我一直在看的例子

int func1 (int n){
       int sum = 0;                                // 1 step
       for (int i = 0; i <= n; i++)                // 1 + 1 + n * (2 steps)
          sum += i;                                // 1 step
       return sum;                                 // 1 step
}                                                  //total steps: 4 + 3n

int func2 (int n){
           int sum = 0;                                // 1 step
           for (int i = 0; i <= n; i++)                // 1 + 1 + n * (2 steps)
              for (int j = 0; j <= n; j++)             // 1 + 1 + n * (2 steps)
                  sum ++;                              // 1 step
           for (int k = 0; k <= n; k++)                // 1 + 1 + n * (2 steps)
               sum--;                                  // 1 step
           return sum;                                 // 1 step
    }      
                                                       //total steps: 3n^2 + 7n + 6

最佳答案

您刚才在此处提出的是非常简单的示例。 在我看来,您只需要了解循环中的复杂性是如何工作的,就可以理解您的示例。

简而言之(非常简短)必须在 asymptotic complexity 中考虑一个循环如下:

loop (condition) :
  // loop body
end loop
  • 循环的条件应该告诉您循环将执行多少次输入的大小相比。。<
  • 主体的复杂性(您可以将主体视为子函数并计算复杂性)必须乘以循环的复杂性。

原因很直观:你在主体中的内容将被重复执行,直到条件得到验证,即循环(以及主体)将被执行的次数。


举个例子:

// Array linear assignment
std::vector<int> array(SIZE_ARRAY);

for (int i = 0; i < SIZE_ARRAY; ++i) {
  array[i] = i;
}

让我们分析一下这个简单的循环:

  • 首先,我们需要选择输入relative 来计算我们的复杂度函数。这种情况非常简单:变量是数组的大小。那是因为我们想知道我们的程序如何响应输入数组大小的增长。

  • 循环将重复 SIZE_ARRAY 次。所以主体将被执行的次数是 SIZE_ARRAY 次(注意:值是可变的,不是常量值)。

  • 现在考虑循环体。 array[i] = i 指令不依赖于数组的大小。它需要未知数量的 CPU 周期,但该数量始终相同,即常量

总而言之,我们重复 SIZE_ARRAY 次指令,该指令占用恒定数量的 CPU 时钟(假设 k 是该值,是常数)。

因此,从数学上讲,该简单程序执行的 CPU 时钟数将为 SIZE_ARRAY * k

随着O Big notation我们可以描述限制行为。这是自变量趋于无穷大时函数将采取的行为。

我们可以这样写:

O(SIZE_ARRAY * k) = O(SIZE_ARRAY)

那是因为 k 是一个常量值,根据 Big O Notation 的定义,该常量不会增长到无穷大(永远是常量)。

如果我们将 SIZE_ARRAY 称为 N(输入的大小),我们可以说我们的函数是一个 O(N)时间复杂度。


最后一个(“更复杂”)的例子:

for (int i = 0; i < SIZE_ARRAY; ++i) {
  for (int j = 0; j < SIZE_ARRAY; ++j) {
    array[j] += j; 
  }
}

如前所述,我们的问题大小与 SIZE_ARRAY 进行了比较。

很快:

  • 第一个循环将执行 SIZE_ARRAY 次,即 O(SIZE_ARRAY)
  • 第二个循环将执行 SIZE_ARRAY 次。
  • 第二个周期的主体是一条指令,它将占用一个固定数量的 CPU 周期,假设这个数字是 k

我们将执行第一个循环的次数乘以循环体的复杂度。

O(SIZE_ARRAY) * [first_loop_body_complexity].

但是第一个循环的主体是:

for (int j = 0; j < SIZE_ARRAY; ++j) {
    array[j] += j; 
}

和前面的例子一样是单循环,我们刚刚计算的是复杂度。它是一个 O(SIZE_ARRAY)。所以我们可以看到:

[first_loop_body_complexity] = O(SIZE_ARRAY)

最后,我们整个的复杂度是:

O(SIZE_ARRAY) * O(SIZE_ARRAY) = O(SIZE_ARRAY * SIZE_ARRAY)

也就是

O(SIZE_ARRAY^2)

使用 N 而不是 SIZE_ARRAY

O(N^2)

关于c++ - 通过计算步数计算算法复杂度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39752084/

相关文章:

algorithm - 寻找封闭骑士之旅的快速算法

c++ - 集合论数据结构

javascript - 当我们需要返回一个值时,为什么我们在递归中需要 "return"?

data-structures - ColdFusion 循环遍历具有键评估的结构失败!我错过了什么?

c++ - 在不破坏元素的情况下调整 std::vector 的大小

c++ - 为什么 noexcept 在编译时不强制执行?

c++ - wxWidgets 安装时 header 路径不正确

c++ - 伪终端和串行设备之间奇怪的字符替换

algorithm - AS3动态文本算法

algorithm - 解决没有成本矩阵的分配问题?