关于Java:关于冒泡排序复杂性的困惑

 2021-02-24 

Confusion on Bubble sort complexity

通过如何计算堆栈溢出时的冒泡排序时间复杂度,我知道冒泡排序的最坏情况的复杂度是大哦= n ^ 2

但是我的困惑是它的派生方式是

Big Oh = n + n - 1 + n - 2 ... + 1 = (n(n + 1))/2 = O(n2)

现在方程(n(n 1))/ 2 = O(n2)是矛盾的。

如果我取n = 10,则(n *(n 1))/ 2 = 55,那么它等于n2的结果是100,实际上接近其一半,所以我们不能说它是? 。

请明确我的疑问。


来自维基百科:

f(x) = O(g(x)) as x goes to infinity if and only if there is a positive constant M such that for all sufficiently large values of x, the absolute value of f(x) is at most M multiplied by the absolute value of g(x).

因此在您的实例中有一个常数:如果我们取M = 3,则对于所有n>0,不等式(n*(n + 1))/2 < 3*(n^2)都成立。

此外,该定义还表示:O(n^2) = O(n^2/180) = O(n^2 + n),依此类推。


Now the equation (n*(n + 1))/2 = O(n^2) is contradictory.

不,不是。

因为它不是方程式。

实际上,O(n^2)实际上是无限功能集f(n)的简写形式,每个函数分别具有以下属性:

limit ( n -> infinity ) of f(n) <= C * n^2 ... for some constant C.

(有更精确的说明方式...)

直观地讲,f(n)是集合O(n^2)的成员,这告诉我们f(n)随着N变得很大而与n^2成比例增长。

很容易证明f(n) = (n*(n + 1))/2是集合O(n^2)

的成员

非正式地,由于N对于此f(n)而言确实很大,所以该等式的(n^2)/2项占主导地位,而n/2则变得无关紧要。


任何排序算法的复杂性取决于比较。在冒泡排序中,我们已经看到总共有N-1个通过。在第一遍中,进行N-1个比较以将最高元素放置在正确的位置。然后在步骤2中,第二高的元素放置在其位置。因此,要计算复杂度,我们必须计算由algo?

进行的比较

使用基本离散数学?

f(n)= (n-1)+(n-2)+(n-3)+.....+ 3 + 2 + 1

f(n)= n(n-1)/2

f(n)= n^2 + O(n) ~ (The constans are ignored for deriving Complexities)

f(n)= O(n^2)

因此,如果O(n ^ 2),则冒泡排序的复杂性。这意味着执行气泡排序所需的时间与n ^ 2成正比,其中n是数组中的元素总数。


准确地说,O(...)是一组函数,而不是数字。有时有些人很懒,写x = O(y)而不是x \\in O(y)

您可以在此表的正式定义列中找到集合O(y)的确切定义:https://en.wikipedia.org/wiki/Big_O_notation#Family_of_Bachmann.E2.80.93Landau_notations

这非正式地是什么意思? O(f(x))包含以相同速度增长的功能。
例如,如果您有g(x) = n^2 + 5n - 7000,则它位于O(n^2)中,因为n^2是函数的主要部分(与确切的定义进行比较)。

此外,可以删除恒定因子。因此,g(x) = 1000n^2也在O(n^2)中。

因此,O(...)仅指示哪些变量以及变量取决于什么。例如,存在一个输入(可能是veerery大),其中函数n^2大于100000000 * n

因此,通常时间复杂度为O(n^2)的算法不如O(n)中的算法。但是,这非常重要,在实践中它可能是可取的,因为第二种算法中的隐藏内容可能是如此之大,以至于第一种算法对于实际发生的输入大小来说更好。但是,第二种算法会变得更好,但是在输入大小上有一个界限(它可能非常大),但是实际上它们可能不会发生。


O符号表示随着输入数量的增加,返回时间如何随输入数量的增加而增加。例如,假设一些代码是O(n)。如果我们要加倍输入,我们希望运行时间会(大约)增加一倍。如果将其增加三倍,我们希望运行时间也将增加三倍。请注意,不管代码运行时的假设确切公式中可能存在任何因素如何,这都是正确的。

可以说与O(n ^ 2)类似:翻倍将导致四倍增长,等等。

所以:

O(n ^ 2)== O(1/2 * n ^ 2)== O(2 * n ^ 2)== 0(1000000000 * n ^ 2)

这是一个不错的教程。


时间复杂度的工作方式是您要查找函数在非常大的值下的行为。替代N的值不是精确的,但对于大值将是近似值。例如,如果N = 1,000,000,并且您的时间复杂度为O(n+1),那么1,000,000和1,000,001是否不同?

这个想法是让您保留那些渐近增长最快的术语。因此,在n*(n+1)/2中,您将保留n^2,因为增长最快。