4

I have array of ints

int array[] = ...

and I can sort it using

Arrays.sort(array);

but Arrays.sort uses quicksort, which sometimes result in O(n^2) complexity. I had an idea to convert it to List and then sort it (mergesort is used, so upper bound is O(n log n)), but the drawback is that it creates a lot of objects due to boxing from int to Integer.

My third approach is this :

array = Arrays.stream(array).sorted().toArray();

I operate only on IntStream, but unfortunately the complexity isn't mentioned in the documentation.

I was looking for similar questions and I have found only this Big-O complexity of java.util.stream.Stream<T>.sorted() which isn't helpful at all, because there are two different answers (first is of course partially wrong, because Arrays.sort isn't always O(n log n)). What about the second one ? I haven't found the proof.

Community
  • 1
  • 1
Pand
  • 79
  • 2
  • 4
    From the Javadoc of [`Arrays.sort`](https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#sort-int:A-): "This algorithm offers O(n log(n)) performance on many data sets that cause other quicksorts to degrade to quadratic performance, and is typically faster than traditional (one-pivot) Quicksort implementations." Your premise is wrong. – Tunaki Jan 16 '16 at 19:55
  • 1
    I'm voting to close this question as off-topic because OP misread the documentation – Denys Séguret Jan 16 '16 at 19:59
  • @Tunaki His premise is not wrong. The implementation may not exhibit *O(n^2)* behaviour as often as others, but it cannot escape exhibiting it for some datasets. – user207421 Jan 16 '16 at 20:03
  • 1
    Are all those downvotes really necessary? – sinclair Jan 16 '16 at 20:04
  • @EJP Well yes but saying "Arrays.sort isn't O(n log n)" is wrong. – Tunaki Jan 16 '16 at 20:04
  • @Tunaki Certainly, but that doesn't invalidate the premise of the question. – user207421 Jan 16 '16 at 20:06
  • 1
    Saying Arrays.sort isn't O(n log n) is of course right. Worst case complexity is O(n^2) and having array with 10^6 elements it might not stop for years.. – Pand Jan 16 '16 at 20:46

4 Answers4

1

You should investigate Heapsort, while slightly slower it guarantees O(n Log n). Quicksort vs heapsort

There is also the textbook explanation here.

Community
  • 1
  • 1
Chad Dienhart
  • 5,024
  • 3
  • 23
  • 30
1

If the range of integers is small you can use Counting Sort, which uses numbers as array-indexes and, unlike comparison-sort algorithms that have a lower bound of O(nlogn) (eg Quicksort or Mergesort), it has a complexity of O(n+k), where k is the range between your min and max value.

Which algorithm to choose always depends on any extra knowledge you may have regarding the distribution of the array elements.

Kostas Kryptos
  • 4,081
  • 2
  • 23
  • 24
1

O(n) time, O(1) space

Use IntArrays.unstableSort(int[] a) from fastutil library.

It uses in-place radix sort for big enough arrays and quicksort for small arrays:

if (to - from >= RADIX_SORT_MIN_THRESHOLD) {
  radixSort(a, from, to);
} else {
  quickSort(a, from, to);
}

O(n log(n)) time, O(n) space and Java 14+

Arrays.sort uses quicksort, which sometimes result in O(n^2) complexity

This is only true if you are using Java 13 or earlier versions. Starting from Java 14 Arrays.sort(int[]) guarantees O(n log(n)) performance in the worst case:

This algorithm offers O(n log(n)) performance on all data sets, and is typically faster than traditional (one-pivot) Quicksort implementations.

https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Arrays.html#sort(int%5B%5D)

This is achieved by resorting to heapsort if recursion becomes too deep:

if ((bits += DELTA) > MAX_RECURSION_DEPTH) {
  heapSort(a, low, high);
  return;
}
Denis Stafichuk
  • 2,415
  • 2
  • 16
  • 29
0

Just implement the mergesort yourself, it's no rocket science. After you have implemented it, do take a little time to run some benchmarks and compare the performance of you implementation with that of Arrays.sort. There may be some surprises waiting for you there.

Also, read up on premature optimization, I think you might find the notion useful.

Dima
  • 39,570
  • 6
  • 44
  • 70
  • 3
    I have no doubt whatsoever that Don Knuth would be astonished to learn that choosing a sorting algorithm would ever be regarded as 'premature optimization'. – user207421 Jan 16 '16 at 20:07
  • @EJP you would? Why? Do you think, he would not consider choosing a sorting algorithm "an optimization"? Your surprise can certainly not have anything to do with the other part of the term, as the property of something being "premature" does not depend on the nature of that action, only on the timing of it. I am really puzzled. What's your objection here? – Dima Jan 16 '16 at 20:11
  • Of course, I can implement it by myself, but I think it is better to first checked if something is implemented. I know about premature optimization, but having array with ~10^6 elements I can't use Arrays.sort, because for some dataset it won't stop for years – Pand Jan 16 '16 at 20:44
  • @Pand what makes you think that? Do you have an example of such dataset? – Dima Jan 16 '16 at 20:50
  • For now I don't have, but it is possible. It happened to my once in online judge Codeforces where I got time limit, because of using Arrays.sort instead of sorting list. You can read about it for example here : http://codeforces.com/blog/entry/7108 – Pand Jan 16 '16 at 20:58
  • Everything is possible ... Well, almost, anyway. "For now I don't have" is the definition of premature optimization – Dima Jan 16 '16 at 21:52