Given an array of values, I want to find the total "score", where the score of each element is the number of elements with a smaller value that occur before it in the array.
e.g.
values: 4 1 3 2 5
scores: 0 0 1 1 4
total score: 6
An O(n^2) algorithm is trivial, but I suspect it may be possible to do it in O(nlgn), by sorting the array. Does anyone have any ideas how to do that, or if it's not possible?
To count the number of elements in the C# array, we can use the count() method from the IEnumerable. It is included in the System. Linq. Enumerable class.
A simple solution would be to use efficient sorting algorithms like Merge Sort, Quicksort, Heapsort, etc., that can solve this problem in O(n. log(n)) time, but those will not take advantage of the fact that there are many duplicated values in the array. A better approach is to use a counting sort.
Looks like what you are doing is essentially counting the number of pairs of elements that are in the incorrect relative order (i.e. number of inversions). This can be done in O(n*log(n)) by using the same idea as merge sort. As you merge, you just count the number of elements that are in the left list but should have been on the right list (and vice versa).
If the range of your numbers is small enough, the fastest algorithm I can think of is one that uses Fenwick Trees. Essentially just iterate through the list and query the Fenwick Tree for how many elements are before it, then insert the number into the tree. This will answer your question in O(nlogm), where n is the size of your list and m is your largest integer.
If you don't have a reasonable range on your integers (or you want to conserve space) MAK's solution is pretty damn elegant, so use that :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With