【问题标题】:Meaning of average complexity when using Big-O notation使用 Big-O 表示法时平均复杂度的含义
【发布时间】:2011-04-23 18:01:58
【问题描述】:

在回复this question 时,cmets 开始就 QuickSort 的复杂性展开辩论。我在大学时记得的是,QuickSort 在最坏的情况下是O(n^2),在一般情况下是O(n log(n)),在最好的情况下是O(n log(n))(但有更严格的限制)。

我需要的是对 average complexity 含义的正确数学解释,以便向相信大 O 符号只能用于最坏情况的人清楚地解释它的含义。

我记得如果要定义平均复杂度,您应该考虑所有可能输入的算法复杂度,计算有多少退化和正常情况。如果当 n 变大时,退化案例的数量除以 n 趋于 0,那么您可以说正常案例的整体函数的平均复杂度。

这个定义正确还是平均复杂度的定义不同?如果它是正确的,有人可以比我更严格地陈述它吗?

【问题讨论】:

  • 关于这个论点,我认为如果你给出运行时间的大 O 符号并且没有限定它,那么你应该谈论最坏的情况,仅仅因为你说的是​​那个时间由具有指定大 O 的函数限制。如果时间是有界的,这意味着最坏情况下的时间是有界的,根据“有界”的定义。但是,如果您说“这是 O(n log n) 平均情况”,那么这是定义明确的,并且意味着您在这个问题中所说的内容。
  • 这个问题可能值得尝试cstheory.stackexchange.com
  • @Chris:虽然该网站的常见问题解答中说“教科书中的典型家庭作业问题”太基础了,但我认为这和那一样基础。
  • 你会在那里得到一页数学符号,对初学者不友好
  • @Chris S:我是一名程序员,但我以前做过一些数学运算,所以这对我来说不是问题。但对其他人来说,拥有更易于访问的东西确实很好。

标签: algorithm complexity-theory big-o


【解决方案1】:

你是对的。

Big O(大 Theta 等)用于测量函数。当您编写 f=O(g) 时,f 和 g 的含义并不重要。它们可以是平均时间复杂度、最差时间复杂度、空间复杂度、表示素数分布等。

最坏情况复杂度是一个采用大小为 n 的函数,它告诉您在给定大小为 n 的输入的情况下,算法的最大步数是多少。

平均案例复杂度是一个采用大小为 n 的函数,它告诉您在给定大小为 n 的输入的情况下算法的预期步数。

正如您所见,最坏情况和平均情况的复杂性是函数,因此您可以使用大 O 来表示它们的增长。

【讨论】:

  • 如果我们学究气,写 f=O(g) 是不太正确的。大 O 是一个集合,所以我们应该写 f \in O(g)
  • @jhclark:在使用大 O 时,写成 = 是一个非常的强烈习惯,请参阅en.wikipedia.org/wiki/Asymptotic_notation#Equals_sign 或渐近符号的具体数学。事实上,除了指出这种特殊性之外,我从未见过任何使用 \in 的教科书。
  • 同意这是惯例——我很迂腐。然而,正如维基百科所说,许多人认为“f = O(g) 是对符号的滥用,因为纯数学通常定义 = 来表示双向相等。我绝对属于认为这种使用 = 相当可恶的阵营.
【解决方案2】:

如果您正在寻找一个正式的定义,那么:

平均复杂度是expected 随机输入的运行时间。

【讨论】:

  • 请报价。 Wiki 文章并没有真正直接相关。
  • 实际上找到它en.wikipedia.org/wiki/Average-case_complexity,+1 为您的回答,看来(如果我们相信维基百科),正式定义实际上是随机输入。
  • 还有关于案例与复杂性检查的概念en.wikipedia.org/wiki/Best,_worst_and_average_case;而且您似乎使用术语“运行时间”来定义边界功能。
  • 谢谢,这正是我想要的。
  • @Unreason:我为那些不知道期望值在数学中意味着什么的人链接。你说得对,这篇文章与问题没有直接关系。
【解决方案3】:

我认为你的定义是正确的,但你的结论是错误的。

如果“坏”案例的比例趋于0,那么平均复杂度不一定等于“正常”案例的复杂度。

例如,假设 1/(n^2) 个案例是“坏”,其余是“正常”,并且“坏”案例恰好采用 (n^4) 次操作,而“正常”案例恰好采用 n操作。

那么平均需要的操作数等于:

(n^4/n^2) + n(n^2-1)/(n^2)

这个函数是 O(n^2),但不是 O(n)。

但在实践中,您可能会发现时间在所有情况下都是多项式的,“坏”情况的比例呈指数级缩小。那时你会在计算平均值时忽略不良情况。

【讨论】:

  • 好的,我同意你的看法。我真的完全按照您的建议来计算平均值的复杂性。这甚至是我在链接问题的 cmets 中放入的微积分。我说我们保持正常情况太快了,这显然并不总是正确的,并且取决于退化情况的复杂性。按照我的说法,糟糕的情况甚至可以永远持续下去,程序永远不会停止,这绝对不是一般的好。
  • @kriss:是的,非暂停案例比我的例子更简单,尽管从技术上讲它不是您正在分析的“算法”。
【解决方案4】:

我们参考Big O Notation in Wikipedia:

令 f 和 g 是在实数的某个子集上定义的两个函数。一个写f(x)=O(g(x)) as x --> infinity if ...

所以定义的前提是函数 f 应该将一个数字作为输入并产生一个数字作为输出。我们在谈论什么输入数字?应该是要排序的序列中的许多元素。我们可以谈论什么输出数字?可能是为了对序列进行排序而进行的许多操作。但是停下来。什么是函数? Function in Wikipedia:

函数是一组输入和一组允许输出之间的关系,具有每个输入与恰好一个输出相关的属性。

我们是否使用先前的定义产生恰好一个输出?不,我们没有。对于给定大小的序列,我们可以获得大量不同的操作。因此,为了确保该定义适用于我们的案例,我们需要将一组可能的结果(操作数)减少为单个值。它可以是最大值(“最坏情况”)、最小值(“最好情况”)或平均值。

结论是,谈论最佳/最差/平均情况在数学上是正确的,而在没有排序复杂性的上下文中使用大 O 表示法有点草率。

另一方面,我们可以更精确地使用大 Theta 表示法而不是大 O 表示法。

【讨论】:

  • 您指出错误的段落仅说明我们可以使用泰勒展开计算平均值的极限,并忽略无关紧要的项。当然,平均值会受到影响,当退化情况不重要时,我会指出一个特定情况。显然,这并不总是正确的。换句话说,当然平均值总是可以定义的,但是当我们想要的不是定义它而是计算它时,这并没有多大帮助。
  • @kriss,我只是不明白“那么你可以说正常情况下整体功能的平均复杂度”。
  • 好的,我应该改变措辞。我的意思是忽略趋向于零的术语(例外情况),只保留“正常情况”术语。
【解决方案5】:

平均案例分析执行以下操作:

取所有固定长度的输入(比如n),将这个长度的所有实例的所有运行时间相加,并建立平均值。

问题是您可能必须枚举所有长度为n 的输入,才能得出平均复杂度。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多