题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
这道题中要求奇数在前半部分,偶数在后半部分,同时还要具有稳定性。
首先,如果这题不要求具有稳定性,那么可以很简单的做到 inplace的 O(n)时间复杂度
public void reOrder(int[] array){
int low = 0;
int high = array.length-1;
while(low<high){
//low向右移动,直到发现偶数
while(low<high && array[low]%2==1){
low++;
}
//high向左移动,直到发现奇数
while(low<high && array[high]%2==0){
high--;
}
swap(array,low,high);
}
}
那么现在,这道题要求具有稳定性。
如果额外引入一个辅助数组空间的话,这个题很简单,这里就不写了。下面给出基于冒泡排序的方法:
第一层for循环,每次将第i个位置排好。冒泡排序具有稳定性
//类似冒泡排序
public void reOrderArray(int [] array){
for (int i = 0; i < array.length;i++){
for(int j = array.length - 1; j>i;j--){
if(array[j-1]%2==0 && array[j]%2==1){//前偶后奇
swap(array,j-1,j);
}
}
}
}
事实上,我们还发现,由于这道题的大小关系只是奇数和偶数,那么在第一层for循环中,每次除了将第一个位置排序好,同时,最后一个位置也排好序了。
因此,代码稍作优化:
//事实上,上面的reOrderArray函数中,每一次冒泡会将首尾都排好。
//因此,第一层循环中只需要走一半即可
public void better_reOrderArray(int [] array){
for (int i = 0; i <= array.length/2;i++){
for(int j = array.length - 1; j>i;j--){
if(array[j-1]%2==0 && array[j]%2==1){//前偶后奇
swap(array,j-1,j);
}
}
}
}