@maaartinus has excellent advice about the naming and structure of your code. I even appreciate his suggestion about doing an odd/even sort. It's slower for larger scales, but the code simplicity sure wins out.
Talking about scales.... part of your question is: What is the minimum space and time complexity we can achieve for this problem?
Well, the sort from maaartinus would be time-complexity of \$O(n \log n)\$ from the sort. That is not horrible, really, but it is not as good as the \$O(n)\$ of your implementation. It would not be possible to beat your \$O(n)\$ time complexity. As for space complexity yours, and maaartinus's jestful sort would both be \$O(1)\$, essentially nothing added.
What's the minimum possible? Time is \$O(n)\$, and space is \$O(1)\$. Bottom line, your code is about as good as you can hope for, in terms of scalability and complexity. I realize that maaartinus is not really serious about converting to a sort, but, in reality... perhaps he should be. The real issue with that is the need to box the values to Integers, etc.
What I really want to comment on, though, is your algorithm. Problems like this have 'landmarks'. Things you look for when processing the data. The landmarks are an indication of how you think... what you think the highlights are.
In your code, your loop changes 1 thing each iteration... either the left pointer, the right pointer, or it swaps a pair. In a sense, your code is:
- loop until done
- is the pointer setup swappable? If yes, then swap them, reloop
- otherwise, bring the pointers one step closer to being swappable
Now, there's nothing wrong with that, but it is not the way I think about things, so I like to code it differently. I like to have "positive states"... where I know where things are at. I would prefer the logic:
- identify something swappable
- if it is successful, swap them, otherwise done.
- loop to 1
To solve things my way, you have to be assertive about your conditions. Here's the code I would use (using names maaartinus suggests):
private static void segregateEvenOdd(int[] array) {
int left = oddToSwap(array, 0, array.length - 1);
int right = eventoSwap(array, array.length - 1, left);
while (left < right) {
int tmp = array[left];
array[left] = array[right];
array[right] = tmp;
left = oddToSwap(array, left + 1, right);
right = evenToSwap(array, right - 1, left);
}
}
How do you read that? Well, it's as follows:
- move left to the first odd value
- move right to the last even value
- if there's a match, then swap them, and go to 1, else end.
There needs to be the implementation of the two helper methods:
private static int evenToSwap(final int[] array, int right, final int left) {
while (right > left && (array[right] & 1) == 1) {
right--;
}
return right;
}
private static int oddToSwap(final int[] array, int left, final int right) {
while (right > left && (array[left] & 1) == 0) {
left++;
}
return left;
}
I much prefer the above solution because it fits my way of thinking. On the other hand, it has other benefits too.... for example, it only checks each value once with the modulo's. Your solution could compare values multiple times.
A worst-case scenario for your code is that you have data that is all odd. In that case, you will check the modulo of the data at data[0] \$2n\$ times. With my code, it will be checked just once.
partitionandstable_partitionalgorithms for these tasks. Surely there must be similiar stuff available for Java? \$\endgroup\$