【问题标题】:Which algorithm is faster O(N) or O(2N)?O(N) 或 O(2N) 哪个算法更快?
【发布时间】:2014-11-04 19:52:29
【问题描述】:

说到大O符号,如果一种算法的时间复杂度是O(N)而另一种是O(2N),那么哪一种更快?

【问题讨论】:

  • 没有O(2N)这样的东西。
  • 不,因为常数倍数在大 O 表示法中没有意义。你需要do some more reading
  • 这些 cmets 实际上提供了很多错误信息。对于 f(n) = 2n,O(f(n)) 是很好定义的。写 O(2n) 绝对有效。然而,O(n) 是 canonical 形式,其中 O(n) = O(cn) 对于任何固定的 c > 0。类似地,O(n + log n) 是有效集合,即使虽然 O(n + log n) = O(n)。
  • @ChrisHayes 那么那个的想法需要解决。
  • @ChrisHayes 问题是人们经常认为 O(f(n)) 是一个函数。它不是——它是一组函数。写出类似 4n + 5 = O(n) 的东西是对符号的滥用。正确的表示法是 4n + 5 ϵ O(n)。

标签: algorithm big-o


【解决方案1】:

O(N) 和 O(2N) 对于少量 N 将显示出显着的增长差异,但随着 N 值的增加,O(N) 将主导增长,系数 2 变得微不足道。所以我们可以说算法复杂度为 O(N)。

示例:

让我们使用这个函数

T(n) = 3n^2 + 8n + 2089

对于 n= 1 或 2,常数 2089 似乎是函数的主要部分,但对于较大的 n 值,我们可以忽略常数和 8n,而可以只专注于 3n^2,因为它对函数的贡献更大增长,如果 n 值仍然增加,系数 3 也似乎微不足道,我们可以说复杂度是 O(n^2)。

详细解释请参考here

【讨论】:

  • 这是一个很好的例子,用更简单的术语解释
【解决方案2】:

大O的定义是:

O(f(n)) = { g |存在 N 和 c > 0 使得 g(n) N }

在英语中,O(f(n)) 是最终增长率小于或等于 f 的所有函数的集合。

所以 O(n) = O(2n)。就渐近复杂性而言,两者都不比另一个“更快”。它们代表相同的增长率 - 即“线性”增长率。​​p>

证明:

O(n) 是 O(2n) 的子集: 设 g 是 O(n) 中的函数。然后有 N 和 c > 0 使得 g(n) N。所以 g(n) N。因此 g 在 O(2n )。

O(2n) 是 O(n) 的子集: 设 g 是 O(2n) 中的函数。然后有 N 和 c > 0 使得 g(n) N. 所以 g(n) N. 因此 g 在 O(n) 中。

通常,当人们提到渐近复杂性(“大 O”)时,他们指的是规范形式。例如:

  • 对数:O(log n)
  • 线性:O(n)
  • 线性:O(n log n)
  • 二次:O(n2)
  • 指数:O(cn) 对于一些固定的 c > 1

(这里有一个更完整的列表:Table of common time complexities

所以通常你会写 O(n),而不是 O(2n); O(n log n),而不是 O(3 n log n + 15 n + 5 log n)。

【讨论】:

  • 你的正式证明非常好,我理解为什么在数学上 O(n) = O(2n) 但你能帮我从逻辑上理解它吗?就像函数 y = x 和 y = 2x 怎么能有相同的增长率。​​span>
  • @darshan 一个有用的方法是通过在 2D 图表上绘制时间复杂度来可视化它。想象一下你的 O(N) 算法从 1 开始,然后是 2、3、4、... N。现在想象你的 O(2N) 算法,它是 2 * N,所以它将从 2 开始,然后是 4、6、8, ... N - 我们可以看到增长率与 N 成正比。关键要记住,我们谈论的是复杂性而不是速度。我们想知道我们的算法是如何增长的——是线性的还是二次的等等?
【解决方案3】:

理论上 O(N) 和 O(2N) 是相同的。

但实际上,O(N) 的运行时间肯定会更短,但并不显着。当 N 足够大时,两者的运行时间将相同。

【讨论】:

  • O(2n) 在概念上是 O(n),因为随着 n 接近无穷大。 O(2n) 将实现细节融入概念细节,请参阅perlmonks.org/?node_id=227909
  • 我不同意,当您提到算法的实用性能时,除了算法复杂性之外,还有更多需要考虑的因素。一种算法可能会在系统内存中跳得更多,这会使其速度变慢,但这还不足以说较低的复杂性可以保证更短的运行时间。
  • 如果我们写的是 O(2N) 与 O(N),我想我们是在讨论两次运行相同实现的实用性,或者 2 是从哪里来的?
  • @cz 有人可能会假设通过将两个 O(n) 操作串在一起,结果是 O(2n),这充其量是对语法的误用。由于我们不知道这两个 O(n) 操作中的线性、次线性或常数因子,因此不要假设标记为 O(2n) 的算法花费的时间是算法 O(n) 的两倍会更安全,或者事实上,它实际上更快或更慢。我们根本无法使用 O(f(n)) 表示法来推断两个 O(n) 函数的绝对或相对运行时间,除了当 n 接近无穷大时的理论上的渐近行为。
【解决方案4】:

这取决于渐近符号隐藏的常数。例如,采用3n + 5 步骤的算法属于O(n) 类。采用2 + n/1000 步骤的算法也是如此。但是2n 小于3n + 5 并且大于2 + n/1000...

这有点像问5 是否小于 1 到 10 之间的某个未指定的数字。这取决于未指定的数字。仅仅知道算法以O(n) 步骤运行并不足以决定采用2n 步骤的算法是否会更快地完成。

实际上,情况比这更糟糕:您是在询问 1 到 10 之间的某个未指定数字是否大于 1 到 10 之间的某个其他未指定数字。您选择的集合相同并不意味着您选择的数字碰巧挑选将是平等的! O(n)O(2n) 是算法的集合,并且因为 Big-O 的定义抵消了乘法因子,它们是相同的集合。集合中的单个成员可能比其他成员更快或更慢,但集合是相同的。

【讨论】:

  • 你能解释一下为什么使用类比“你问的是 1 到 10 之间的某个未指定的数字是否大于 1 到 10 之间的其他未指定的数字”而不是“你问的是1 到 10 之间的未指定数字大于 1 到 10 之间的其他未指定数字并将该数字乘以 2"?
  • @McKevin 我试图简化情况,而不是真正解决问题。它使直观的飞跃变得更小,然后其余的就更容易了。
【解决方案5】:

Timothy Shield 的answer 是绝对正确的,O(n)O(2n) 指的是同一组函数,所以一个不是“比另一个更快”。不过,需要注意的是,更快并不是一个适用于此的好词。

Wikipedia's article on "Big O notation" 在您可能使用“更快”的地方使用了“较慢增长”一词,这是更好的做法。这些算法是根据它们随着 n 的增加而增长的方式来定义的。

人们很容易想象一个 O(n^2) 函数在实践中比 O(n) 更快,尤其是当 n很小或者如果 O(n) 函数需要复杂的转换。该符号表明,对于两倍的输入,可以预期 O(n^2) 函数花费的时间大约是以前的 4 倍,其中 O(n) 函数所需的时间大约是以前的两倍。

【讨论】:

    猜你喜欢
    • 2021-12-22
    • 1970-01-01
    • 2014-06-13
    • 2021-09-25
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    相关资源
    最近更新 更多