简体   繁体   中英

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

Algorithm

Basically, is the below algorithm O(n log n) or O(n^2). I'm sure the algorithm has a name; but I'm not sure what it is.

pseudo-code:

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

in 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;
}

Simply speaking, this algorithm walks a list, and inserts each element into a newly created list in its correct location.

Complexity

This is how I think about the complexity of this algorithm:

  • For each element in the list, dest increases in size by 1
  • This means that, at each step, the algorithm has a worst-case time of the size of dest
  • Summing those up, we'd get 0 + 1 + 2 + 3 + ... + n
  • The sum of all natural numbers up to n = n(n+1)/2
  • This simplifies to (n^2 - n)/2 , and by removing constant & low degree terms, we get O(n^2)

Therefore the complexity is O(n^2).

However, I was recently browsing this answer , in which the author states:

O(n log n): There was a mix-up at the printer's office, and our phone book had all its pages inserted in a random order. Fix the ordering so that it's correct by looking at the first name on each page and then putting that page in the appropriate spot in a new, empty phone book.

This, to me, sounds like the same algorithm, so my question is:

  • Is the algorithm I described the same as the one described by @John Feminella?
  • If it is, why is my calculation of O(n^2) incorrect?
  • If it isn't, how do they differ?

The algorithm you have described is different than the O(n log n) algorithm described in the linked answer. Your algorithm is, in fact, O(n^2).

The key difference is in the way the correct location for each element is determined. In you algorithm, each element is searched in order, meaning that you check every element against every other already-sorted element. The linked algorithm is predicated on the O(log n) method used for finding a person's name:

O(log n): Given a person's name, find the phone number by picking a random point about halfway through the part of the book you haven't searched yet, then checking to see whether the person's name is at that point. Then repeat the process about halfway through the part of the book where the person's name lies. (This is a binary search for a person's name.)

If you use this method to find where each page should go in the new book, you only end up doing O(log n) operations for each page, instead of O(n) operations per page as in your algorithm.


Incidentally, the algorithm you have described is essentially an insertion sort , although it uses two lists instead of sorting in-place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM