0

I am looking for an O(n) sort algorithm where n is the number of elements to sort. I know that highly optimized sorting algorithms are O(n log n) but I was told that under the following condition we can do better. The condition is:

  • We are sorting numbers in a small enough range, say 0 to 100.
Stephany
  • 29
  • 6
  • 1
    Use [counting sort](https://en.wikipedia.org/wiki/Counting_sort#Variant_algorithms) . You only need an array of size 101 to hold the counts for the number of instances of values from 0 to 100. – rcgldr Aug 22 '17 at 03:03

1 Answers1

2

Say we have the following

unsortedArray = [4, 3, 4, 2]

Here is the algorithm:

Step 1) Iterate over the unsortedArray and use each element as the index into a new array we call countingArray. The value we will hold in each position is the count of times that that number appears. Each time we access a position we increment it by 1.

countingArray = [0, 0, 0, 0, 0, ..., 0, 0, 0, 0]   // before iteration
countingArray = [0, 0, 0, 0, 1, ..., 0, 0, 0, 0]   // after handling 4
countingArray = [0, 0, 0, 1, 1, ..., 0, 0, 0, 0]   // after handling 3
countingArray = [0, 0, 0, 1, 2, ..., 0, 0, 0, 0]   // after the second 4
countingArray = [0, 0, 1, 1, 2, ..., 0, 0, 0, 0]   // after handling 2

We can allocate countingArray in advance because the range of the numbers we wish to sort is limited and known a-priori. In your example countingArray will have 101 elements.

Time complexity of this step is O(n) because you are iterating over n elements from unsortedArray. Inserting them into countingArray has constant time complexity.

Step 2) As shown in the example above countingArray is going to have positions with value 0 where there were no numbers to count in unsortedArray. We are going to skip these positions in the following iteration we will describe.

In countingArray non-zero positions define a number that we want to sort, and the content in that position define the count of how many times that number should appear in the final sortedArray.

We iterate over countingArray and starting at the first position of sortedArray put that number into count number of adjacent positions. This builds sortedArray and takes O(n).

countingArray = [0, 0, 1, 1, 2, ..., 0, 0, 0, 0]

// After skipping the first 2 0s and seeing a count of 1 in position 2
sortedArray = [2, 0, 0, 0]

// After seeing a count of 1 in position 3
sortedArray = [2, 3, 0, 0]

// In position 4 we have a count of 2 so we fill 4 in 2 positions
sortedArray = [2, 3, 4, 4]

=======

Total time complexity is O(n) * 2 = O(n)

r2b2
  • 21
  • 4
  • 1
    Haven't you just reinvented Counting Sort but with an unnecessary complication by involving a Map instead of using the array from the start – harold Aug 22 '17 at 02:48
  • Didn't mean to invent anything, just provide an answer @harold. I'll edit my post. – r2b2 Aug 22 '17 at 04:28