面试题21:调整数组顺序使奇数位于偶数前面
一、题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
二、问题分析
最简单的思路是扫描数组,遇到偶数就大动干戈,将后面的数字全部向前移动一位,末尾给这个偶数。不过,你也能感觉到这样效率十分低下,要明白只完成基本功能的解法,仅仅适用于初级程序员。
下面介绍的这套解法,非常好用且常见。
我们维护数组的两个索引
一个索引,从前往后走,如果遇到奇数则索引后移,直到遇到偶数,这个时候要与另外一个索引协作,才能把该偶数放在数组后面。
另外一个索引,从后往前走,遇到偶数时指针前移,遇到奇数时,则恰好可以与之前提到的索引所指的偶数进行调换。
这种方法效率是非常高的。我们经常在数组和链表这种线性数据结构中维护两个索引或者指针做处理。
三、问题解答
位运算的应用,之前探讨得那么详细,都还记得吧!
public void reOrderArray(int [] array) {
if(array == null || array.length == 0) {
return;
}
int length = array.length;
int low = 0;
int high = length-1;
int temp;
while(low < high){
//向后移动low,直到它指向偶数
while(low<length && (array[low]&1) != 0) {
low++;
}
//向前移动high,直到它指向奇数
while(high>=0 && (array[high]&1) == 0) {
high--;
}
if(low<high){
temp=array[low];
array[low]=array[high];
array[high]=temp;
}
}
}
如果题目含有附加要求:
保证调整后的数组中,奇数和奇数之间,偶数和偶数之间的相对位置不变。
上面的方法就没法实现,可以采用类似于“直接插入排序”的方法:从头开始遍历,遇到奇数时,将该奇数插入到该奇数前面的偶数之前。
如:从头开始遍历246183,遇到奇数1时,将1插入到246之前,变为:124683;该插入的实质是:奇数前面的所有偶数往后移一位,空出的位置放入该奇数
具体实现:
public void reOrderArray(int [] array) {
if(array==null || array.length==0) {
return;
}
int length = array.length;
int temp,j;
for(int i=1;i<length;i++) {
if((array[i]&1) != 0) {
j=i;
temp=array[j];
while((j>0)&&(array[j-1]&1)==0) {
array[j]=array[j-1];
j--;
}
array[j]=temp;
}
}
}