big-O表示法中的n是什么?

时间:2014-05-31 21:15:37

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

问题很简单,但我找不到足够好的答案。在the most upvoted SO question regarding the big-O notation上,它说:

  

例如,通常根据比较操作比较排序算法(比较两个节点以确定它们的相对排序)。

现在让我们考虑简单的冒泡排序算法:

for (int i = arr.length - 1; i > 0; i--) {
    for (int j = 0; j < i; j++) {
        if (arr[j] > arr[j+1]) {
            switchPlaces(...)
        }
    }
}

我知道最坏的情况是O(n²),最好的情况是O(n),但究竟是什么n?如果我们尝试对已经排序的算法进行排序(最好的情况),我们最终什么也不做,那为什么它仍然是O(n)?我们仍在循环2个for循环,所以如果有的话,它应该是O(n²)n不能是比较操作的数量,因为我们仍然比较所有元素,对吗?

4 个答案:

答案 0 :(得分:5)

在分析排序算法的Big-O性能时,n通常表示您要排序的元素数量。

因此,例如,如果您使用冒泡排序对n项进行排序,则最坏情况下的运行时性能将为O(n 2 )的顺序操作。这就是为什么冒泡排序被认为是一种极差的排序算法,因为它不能随着要排序的元素数量的增加而很好地扩展。随着要排序的元素数量线性增加,最坏情况的运行时间会逐渐增加。

这是一个示例图,演示了当问题大小N增加时各种算法如何根据最坏情况运行时进行扩展。深蓝色线表示线性缩放的算法,而品红色/紫色线表示二次算法。

请注意,对于足够大的N,二次算法最终需要比线性算法更长的时间来解决问题。

Running time graphs

取自http://science.slc.edu/~jmarshall/courses/2002/spring/cs50/BigO/的图表。

另见

答案 1 :(得分:5)

我认为这里有两件事情变得混乱,n以及受到Big-O分析限制的n的功能。

按照惯例,对于任何算法复杂度分析,n是输入的大小,如果没有指定任何不同。对于任何给定的算法,输入大小有几个有趣的函数,可以计算asymptotic bounds,例如Big-O。

排序算法最常用的这种函数是最坏情况下的比较数。如果有人说排序算法是O(n^2),而没有指定其他任何内容,我会认为它们意味着最差情况下的比较计数为O(n^2),其中n是输入大小。

另一个有趣的功能是除了要排序的数组之外的工作空间量,空间量。冒泡排序的工作空间为O(1),为常量空间,因为无论数组大小如何,它只使用一些变量。

冒泡排序可以编码为在最佳情况下仅进行n-1数组元素比较,通过任何不进行交换的传递完成。请参阅此伪代码implementation,该代码使用swapped来记住是否存在任何交换。如果数组已经排序,则第一遍不进行交换,因此排序在一次通过后结束。

答案 2 :(得分:3)

n通常是输入的大小。对于数组,这将是元素的数量。

要查看不同的案例,您需要更改算法:

for (int i = arr.length - 1; i > 0 ; i--) {
    boolean swapped = false;

    for (int j = 0; j<i; j++) {
        if (arr[j] > arr[j+1]) {
            switchPlaces(...);
            swapped = true;
        }
    }

    if(!swapped) {
        break;
    }
}

您的算法的最佳/最差情况都是O(n^2),但有可能提前返回,最好的情况现在是O(n)

答案 3 :(得分:0)

n是数组长度。您希望找到T(n)算法复杂度。

访问内存然后检查条件是非常昂贵的。因此,您将T(n)定义为访问存储器的数量。

在给定的算法中,BC和WC使用O(n ^ 2)访问内存,因为你检查if条件O(n ^ 2)次。

提高复杂性:持有一个标志,如果你没有在主循环中进行任何交换,这意味着你的数组已经排序,你可以休息一下。

现在,在BC中,数组已经排序,您可以访问所有元素,因此O(n)。 在WC中仍然是O(n ^ 2)。