if(numbers.length == 0 || numbers.length == 1) {
Could be
if (numbers.length <= 1) {
Trivial time improvement (perhaps none; the compiler may optimize the original). Mostly preferable for simplicity's sake.
int indexForUniqueElements = 0;
for (int index = 0; index < numbers.length - 1; index++) {
if (numbers[index] != numbers[index+1]) {
numbers[indexForUniqueElements++] = numbers[index];
}
}
This is more problematic. What happens if the elements of the array are already unique? You'll copy the entire array for no reason. Consider breaking this up into two loops.
int uniqueCount = 1;
while (uniqueCount < numbers.length && numbers[uniqueCount - 1] != numbers[uniqueCount]) {
uniqueCount++;
}
for (int index = uniqueCount + 1; index < numbers.length; index++) {
if (numbers[index - 1] != numbers[index]) {
numbers[uniqueCount] = numbers[index];
uniqueCount++;
}
}
Now, we skim over all the unique numbers. Once we find the first duplicate, we stop. The earliest that duplicate can be is position 1. Because there are no numbers before that to duplicate. We don't have to copy any of these numbers, as they are already in the array.
The second loop copies subsequent unique numbers over top the duplicates and numbers out of order. If there are no duplicates (the first loop skimmed the entire array), then the second loop won't run at all.
I changed the name to uniqueCount
because I found it more descriptive of what the variable holds. At any moment, it tells us how many known unique elements are in the array. By contrast, I don't really know what an indexForUniqueElements
is. I figured it out, but with uniqueCount
, I don't need to do so.
I moved the increment of uniqueCount
in the second loop to its own line for readability.
This saves the extra assignment at the end of your loop. Your loop is trying to copy the number at the lower index of the comparison. My loop assumes that they are already in the right place. It copies the number at the higher index. Another trivial improvement (sometimes this will not do an assignment at the end when your original code would have).
This approach will not change the asymptotic performance. It's still \$\mathcal{O}(n)\$. But it may make the program run faster, as it saves copying values that are already in the right place. And copying is an expensive operation.
The only way to make a significant improvement from here would be to include the duplicate check with the sort. I.e. remove duplicates as you sort. But if you don't have control over the sort, there is no way that you can do that.