After going through the array once, save the hash map for visible values. As you said, only log(n) different values exist.
Now you have a list of all the different values - sorting them will take lon(n)*log(log(n))
Once you have sorted uniq, how easy it is to compose the original array: the maximum value will take cells n/2 , the second will take n/4 , etc.
The total runtime of O(n + lon(n)*log(log(n)) + n) , which is O(n)
source share