You can solve the problem in O(n)
time. Let me explain the algorithm, and you'll implement it in Java.
Count each item occurence, organize them in a map. Here we have
map = {
{2, 2}, // number 2 appears 2 times
{3, 3}, // number 3 appears 3 times
}
If any number appears 2 or more times, start summation from 1
otherwise from 0
.
Here we have number 2 appears 2 times, so we should start from 1
sum = 1;
Then we loop over array
and update both map
and sum
:
v = array[i];
sum += array.length - i - map[v];
map[v] -= 1;
Let's have a look what's going on:
i : v : sum : map
-----------------------------------
0 : 2 : 1 + 3 = 4 : {{2, 1} {3, 3}}
1 : 3 : 4 + 1 = 5 : {{2, 1} {3, 2}}
2 : 2 : 5 + 2 = 7 : {{2, 0} {3, 2}}
3 : 3 : 7 + 0 = 7 : {{2, 0} {3, 1}}
4 : 3 : 7 + 0 = 7 : {{2, 0} {3, 0}}
Finally, return the sum
.
Edit: Brief logics explanation:
If we have two or more equal items, then we can swap them and have the array unchanged. This is a special solution so we start summing from 1
in this case.
Now let's count all the swaps which change the array. Note, that when swapping we sould not count a swap twice:
... a ... b ...
^ ^
swap(a, b) == swap(b, a)
To prevent this double count let operate with swap(a, b)
only (b
to the right of a
). How many swap (array[i], ...)
do we have?
swap(array[i], array[i + 1])
swap(array[i], array[i + 2])
...
swap(array[i], array[length - 1])
we have length - 1 - i
swaps. However, we should subtract the number of items to the right of array[i]
which are equal to array[i]
(swapping equal items doesn't produce a new array). With a help of map
we can easily subtract the required number:
map[array[i]] -= 1; // array[i] is not to the right of itself
sum += length - 1 - i - map[array[i]]