【问题标题】:Big-O of Nested-for-loops: Linear or Quadratic?嵌套循环的大 O:线性还是二次?
【发布时间】:2015-11-10 16:30:19
【问题描述】:

我试图了解如何知道算法中的嵌套循环是否产生线性或二次Big-Oh 复杂性。这是我想出的几个例子,但与暴力循环和图形遍历有关。我试着

我的思路是否正确?

示例 1:

N = ? // Number of elements in an array of integers
For i = 1 to N
    For j = 1 to N
        Print "foo"
  • 复杂度: O(N^2)
  • 为什么? 因为我们有两个嵌套的 for 循环,它们将迭代相同的次数。因为在运行时我们不知道N的值,那么我们不得不说复杂度是O(N^2)?但是,如果我们硬编码 N=20,那么我们会有 O(N)?

示例 2:

N = ? // Number of elements in an array of integers
For i = 1 to log(N)
    For-each edge of log(N)
        Print "foo"
  • 复杂度: O(log(N)^2)
  • 为什么?因为我们有两个嵌套的 for 循环,它们将迭代相同的 log(N) 次。

示例 3:

V = ? // Total number of nodes in a graph
E = ? // Total number of edges in a graph (not of each iteration-node)
For i = 1 to V
    For j = 1 to E
        Print "foo"
  • 复杂度: O(V*E)
  • 为什么? 因为我们不知道 V = E,所以我们不能说 O(V^2) 或 O(E^2)。我们不知道 V>=E 还是 V

示例 4:

V = ? // Total number of nodes in a graph
For i = 1 to V
    For-each edge of V[i]
        Print "foo"
  • 复杂度: O(|V| + |图中的边|)
  • 为什么? 因为我们知道|图中的边| != |V|,因此迭代次数不成比例。当图是有向图还是无向图时,这是否重要?

【问题讨论】:

  • 在您的任何示例中都没有n,所以说O(n)O(n^2) 毫无意义。
  • 对不起编译器。我已经修复了区分大小写的问题
  • 另外,你不知道 |E| > |V|;例如,一个图可以有很多顶点而根本没有边。如果您确实有一个图表证明这是真的,那么O(|V|+|E|) = O(|E|)
  • 同意。正确的说法是|E| != |V|

标签: algorithm big-o time-complexity nested-loops asymptotic-complexity


【解决方案1】:

Big-O 表示法描述了算法的运行时间如何随着输入的大小而变化。

在示例 1 中,如果您将 N 硬编码为 20,则输入没有缩放。算法实际上变成了O(1)

示例 2 类似于您对示例 1 的直觉,只是每个循环仅运行 log(n) 次迭代。

对于示例 3,我将其描述为在 O(mn) 时间内运行(m = 边数,n = 顶点数),而不是 O(n^2)

最后一个例子实际上比我第一次认为的要微妙一些(感谢@Hurkyl!)。

边由顶点划分,因此除了运行外循环|V| 次外,您还可以有效地运行内循环总共2|E| 次。这导致您的算法复杂度为O(|V| + 2|E|)。常量在 big-o 表示法中通常被忽略,因此这被认为与 O(|V| + |E|) 相同。

【讨论】:

  • 系统发育:我添加了最后一个示例。请看一下。我的道歉。
  • @Phylogenesis:您没有考虑第三个(现在是第四个,自编辑以来)示例;内部循环恰好执行2|E| 次。
  • @Hurkyl 好点。你是绝对正确的 - 我会修正我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-08
  • 1970-01-01
  • 2015-05-19
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
相关资源
最近更新 更多