O(n ^ 2)或O(n log n)?

时间:2017-06-24 01:23:05

标签: algorithm time-complexity big-o

算法

基本上,是以下算法O(n log n)或O(n ^ 2)。我确定算法有一个名字;但我不确定它是什么。

伪码:

def sort(list):
    dest = new list
    for each element in list (call it a):
        for each element in dest (call it c):
            if a <= c, insert a into dest directly before c
    return dest
Java中的

public static List<Integer> destSort(List<Integer> list) {
    List<Integer> dest = new ArrayList<>();
    for (Integer a : list) {
        if (dest.isEmpty()) {
            dest.add(a);
        } else {
            boolean added = false;
            for (int j = 0; j < dest.size(); j++) {
                int b = dest.get(j);
                if (a <= b) {
                    dest.add(j, a);
                    added = true;
                    break;
                }
            }
            if(!added) {
                dest.add(a);
            }
        }
    }
    return dest;
}

简单地说,该算法遍历列表,并将每个元素插入到正确位置的新创建列表中。

复杂性

这就是我对该算法复杂性的看法:

  • 对于列表中的每个元素,dest的大小增加1
  • 这意味着,在每一步,算法都有一个大小为dest
  • 的最坏情况时间
  • 总结一下,我们得到0 + 1 + 2 + 3 + ... + n
  • 所有自然数的总和,最多为n = n(n+1)/2
  • 这简化为(n^2 - n)/2,并删除常量&amp;低学位,我们得到O(n ^ 2)

因此复杂度为O(n ^ 2)。

但是,我最近在浏览this answer,其中作者声明:

  

O(n log n):打印机办公室和我们的手机混淆了   本书以随机顺序插入所有页面。修复订单   通过查看每个页面上的第一个名称然后它是正确的   将该页面放在一个新的空电话簿中的适当位置。

对我来说,这听起来像是相同的算法,所以我的问题是:

  • 我描述的算法是否与@John Feminella描述的算法相同?
  • 如果是,为什么我的O(n ^ 2)计算不正确?
  • 如果不是,它们有何区别?

1 个答案:

答案 0 :(得分:2)

您描述的算法与链接答案中描述的O(n log n)算法不同。事实上,你的算法是O(n ^ 2)。

关键区别在于确定每个元素的正确位置。在您的算法中,按顺序搜索每个元素,这意味着您将检查每个元素与其他已经排序的元素。链接算法基于用于查找人名的O(log n)方法:

  

O(log n):根据一个人的姓名,通过在您尚未搜索的书的一半左右选择一个随机点来查找电话号码,然后检查是否这个人的名字就在那一点上。然后在书的一部分中间重复这个过程。 (这是对人名的二元搜索。)

如果您使用此方法查找新书中每个页面的位置,您最终只能为每个页面执行O(log n)操作,而不是像算法一样每页执行O(n)操作。 / p>

顺便提一下,您所描述的算法基本上是insertion sort,尽管它使用两个列表而不是就地排序。