Sorting the list of number's digits and getting the 1st and 2nd biggest digits will give you at best O(n * log n)
time complexity (assuming you will use Quick Sort).
You can achieve somewhat better performance if you will use another approach: partition (reorder) your array (as in quick sort), so you'll have a pivot value which divides your array in two parts: those which are less than pivot are in the left part (left sub-array), those which are bigger are in the right part (right sub-array). Check the index of the pivot:
- if it's equal to the size of an array of digits minus 2, than it's the second biggest element (the first biggest is next to it, in the right sub-array);
- if the index of pivot is less than size of an array of digits minus 2, repeat the partitioning for the right sub-array;
- if the index of pivot is bigger than size of an array of digits minus 2, repeat the partitioning for the left sub-array;
At some point your pivot will be the the second element from the end of an array, which means that it's the second biggest element, and the biggest number is in the end of an array (because of the way you get the pivot). The time complexity will be better than for a quick sort, because after each partition you're partitioning only one sub-array, not both of them.
You can extend this approach to get not only the 1-st and 2-nd largest digits, but k-th (arbitrary highest) digit, and not only largest, but smallest also.
Check out the piece of code I've written couple of days ago:
public Long selectKthElement(int left, int right, int k, Type type) {
int med = partitionIt(left, right);
if ((type.equals(Type.Smallest) && med == k - 1) || (type.equals(Type.Largest) && med == nElems - k)) {
return theArray[med];
} else if (type.equals(Type.Smallest) && med > k || type.equals(Type.Largest) && med > nElems - k) {
return selectKthElement(left, med - 1, k, type);
} else if (type.equals(Type.Smallest) && med < k || type.equals(Type.Largest) && med < nElems - k){
return selectKthElement(med + 1, right, k, type);
} else {
// impossible case, but the source code won't compile w/o the else
return null;
}
}
Here theArray
is an array of numbers' digits, partitionIt
method reorders an array and returns the index of median, you can either figure out how to write the implementation of it yourself, or search through the web.