【问题标题】:Are 2^n and n*2^n in the same time complexity?2^n 和 n*2^n 是否具有相同的时间复杂度?
【发布时间】:2014-03-12 22:59:59
【问题描述】:

我发现的有关时间复杂度的资源不清楚何时可以忽略时间复杂度方程中的项,特别是对于非多项式示例。

我很清楚,对于 n2 + n + 1 形式的东西,最后两个术语是微不足道的。

具体来说,给定两个分类,2n 和 n*(2n),第二个的顺序是否与第一个相同?那里的额外 n 乘法重要吗?通常资源只是说 xn 呈指数增长并且增长得更快......然后继续前进。

我可以理解为什么它不会因为 2n 会大大超过 n,但是因为它们没有被加在一起,所以在比较两个方程时会非常重要,实际上是差异它们之间永远是 n 的一个因子,至少可以说这似乎很重要。

【问题讨论】:

  • 在我看来,鉴于 NLogN 被认为严格比 N 慢,但大多数人并不真正关心多少,可以肯定地说 N2^N 比 2^N 慢,但还不够“慢”让人们关心..
  • @tobias_k,我理解这一点,但考虑 O(n!) 的例子。额外的 n 项真的会有所不同吗? O(n!) 到 O(n*n!) 就像 O(n!) 到 O((n+1)!) 也就是同一个图简单地移动了。但是增长是一样的……在这种情况下,即使一个严格来说很大,增长是不同的吗?这不是时间复杂度所关心的吗?
  • @JackWu 但大多数人并不真正关心多少,除非您必须使用 nlogn 而不是 n 对数亿条记录进行排序 :)
  • 其实n! = o((n+1)!),也就是严格渐近地增长缓慢。
  • 请注意,这与复杂性理论无关,它“只是”关于渐近线。另外,这种问题在Computer Science 上可能会更好。

标签: algorithm big-o complexity-theory time-complexity


【解决方案1】:

查看n⋅2ⁿ 更大的一种快速方法是更改​​变量。让m = 2ⁿ。然后n⋅2ⁿ = ( log₂m )⋅m(在m = 2ⁿ两边取以2为底的对数得到n = log₂m),你可以很容易地证明m log₂mm增长得更快。

【讨论】:

  • 谢谢!这是我认为最好的答案。基于正式定义的证明是正确的,但如果你有某种绊脚石需要克服,那么一个非常舒适和熟悉的类比会做得最好、最快。
  • 愚蠢的问题,lg 是什么?以 2 为底的对数?
  • 这是一个懒惰的缩写。在计算机科学中,它往往意味着以 2 为底,因为它主要来自分而治之的策略。在大 O 表示法中,它可以表示任何东西,因为一个数字的以 x 为底的对数与其以 y 为底的对数仅相差一个常数因子,而与 x 和 y 无关。
  • 回想起来,我应该注意到lg 是 ISO 表示以 10 为底的对数,而不是讨论渐近运行时间时最常用的与基数无关的用法。见en.wikipedia.org/wiki/Logarithm#Particular_bases
  • 好吧,当然,但我不明白为什么 m log m 的增长速度比 m 快,而不是 n 2^n 的增长速度比 2^n 快。
【解决方案2】:

您必须查看大 O 的正式定义 (O) 才能回答这个问题。

定义是f(x) 属于O(g(x)) 当且仅当极限limsup<sub>x → ∞</sub> (f(x)/g(x)) 存在,即不是无穷大。简而言之,这意味着存在一个常数M,因此f(x)/g(x) 的值永远不会大于M

对于您的问题,让f(n) = n ⋅ 2<sup>n</sup>g(n) = 2<sup>n</sup>。那么f(n)/g(n) 就是n,它仍然会无限增长。因此f(n)不属于O(g(n))

【讨论】:

  • 更容易阅读的定义见here
  • 正式来说,不能取O(f(x)/g(x))的限制; big-O 通知是一组函数的简写,而不是您可以限制其值的单个函数。但是,我认为如果lim(x-&gt;infinity) f(x)/g(x) 存在,您确实可以证明f(x) = O(g(x))
  • 限制不一定存在;对于足够大的 x,该比率只需要以常数为界。例如,2+sin(x) 在 O(1) 中,但 (2+sin(x))/1 没有接近 x->infinity 的极限。
  • 使用lim sup 而不是lim,定义将是正确的。
  • @IvayloStrandjev 请注意,您的简短描述不正确。这对于足够大的x 必须是正确的,而不是对于x 的所有值。
【解决方案3】:

我同意n⋅2ⁿ 不在O(2ⁿ) 中,但我认为它应该更明确,因为限制高级用法并不总是成立。

根据 Big-O 的正式定义:f(n)O(g(n)) 中,如果存在常量 c &gt; 0n₀ ≥ 0,那么对于所有 n ≥ n₀,我们都有 f(n) ≤ c⋅g(n)。很容易证明f(n) = n⋅2ⁿg(n) = 2ⁿ 不存在这样的常量。但是可以证明g(n)O(f(n))中。

换句话说,n⋅2ⁿ 的下限为2ⁿ。这是直观的。尽管它们都是指数型的,因此在大多数实际情况下都不太可能使用它们,但我们不能说它们的顺序相同,因为2ⁿ 的增长速度必然比n⋅2ⁿ 慢。

【讨论】:

  • f(n) = 2*2^n 我想你的意思是n*2^n
【解决方案4】:

我不反对其他说n⋅2ⁿ 增长速度快于2ⁿ 的答案。但是n⋅2ⁿ 的增长仍然只是指数级的。

当我们谈论算法时,我们经常说时间复杂度呈指数增长。 因此,我们认为2ⁿ3ⁿeⁿ2.000001ⁿ 或我们的n⋅2ⁿ 是具有指数增长的同一组复杂性。

为了给它一点数学意义,我们考虑一个函数f(x),如果存在这样的常数c &gt; 1,那么函数f(x) = O(c<sup>x</sup>)会以指数方式增长(不快于)。

对于n⋅2ⁿ,常数c 可以是大于2 的任何数字,我们以3 为例。那么:

n⋅2ⁿ / 3ⁿ = n ⋅ (2/3)ⁿ,对于任何n,这都小于1

所以2ⁿ 的增长速度比n⋅2ⁿ 慢,最后一个又比2.000001ⁿ 慢。但它们三个都呈指数级增长。

【讨论】:

  • 在最后一个示例中,n*2^n 大于 2.000001^n,直到 n = 34,726,000。那时 2^n 是一个超过 1000 万位的数字,所以这并不重要......
  • @gnasher729 这只是一个常数,我们可以省略它,因为 f(n) 和 c*f(n) 在 big-O 方面具有相同的复杂性。例如40'000'000*2.000001^n 立即大于 n*2^n。但你是对的,这并不重要,我想说一旦我们达到指数增长(除非我们只得到 n 的小值),这并不重要。
【解决方案5】:

您问“第二个与第一个的顺序相同吗?那里的额外 n 乘法重要吗?”这是两个不同的问题,有两个不同的答案。

n 2^n 渐近增长比 2^n 快。这就是那个问题的答案。

但是你可以问“如果算法 A 需要 2^n 纳秒,而算法 B 需要 n 2^n 纳秒,那么最大的 n 是多少,我可以在一秒/分钟/小时/天/月/年?答案是 n = 29/35/41/46/51/54 vs. 25/30/36/40/45/49。实践上差别不大。

在这两种情况下,可以在时间 T 内解决的最大问题的大小都是 O (ln T)。

【讨论】:

    【解决方案6】:

    非常简单的答案是“否”

    2^nn.2^n

    n.2^n &gt; 2^n 中看到任何n&gt;0

    或者你甚至可以通过在两边应用日志来做到这一点,然后你得到

     n.log(2)    <    n.log(2) + log(n) 
    

    因此通过两种类型的分析

    1. 代入数字

    2. 使用日志

    我们看到n.2^n 明显大于2^n

    所以如果你得到一个等式

    O ( 2^n + n.2^n )可以替换为O ( n.2^n)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 2015-05-08
      • 2021-05-05
      • 2015-08-04
      相关资源
      最近更新 更多