《剑指offer》刷题——【高质量的代码】面试题面试题21:调整数组顺序是奇数位于偶数前面(java实现)
一、题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部
分,所有的偶数位于数组的后半部分。
二、题目分析
方法一:从头遍历 O(n^2)
- 从头扫描数组,每碰到一个偶数,取出这个数字,并把位于这个数字后面的所有数字往前挪动一位;
- 挪完之后,数组末尾空位,把取出的偶数放在空位上
- 每碰到一个偶数需要移动O(n)个数字
- 总时间复杂度:O(n^2)
方法二:双指针 O(nlogn) ——未考虑奇数间、偶数间相对位置不变【类似快排】
- 双指针:初始化分别指向数组的首尾元素,一个从头至尾移动,一个从尾至头移动
- 第一个指针向后移动,直到找到第一个偶数;
- 然后第二个指针向前移动,直到找到第一个奇数;
- 此时交换两个数字;
- 重复上述操作,直至两指针相遇
- 两个指针相遇之前,第一个指针总是位于第二个之前
方法三、可扩展解法
-
为提高代码的可重用性,我们将代码解耦:
- 判断数字是不是符合标准
- 拆分数组,即将元素按照规定方式放置
-
可解决类似问题,只需新定义一个判断标准函数
- 把数组中的数按照大小分为两部分,所有负数都在非负数的前面
- 把数组中的数分为两部分,能被3整除的数都在不能被3整除的数的前面
方法四、考虑奇数间、偶数间相对位置不变O(n^2)——【类似插入排序】
- 遍历每一个元素
- 若当前遍历的元素为奇数,则向前遍历交换
- 直到当前奇数插入到正确的位置
- 继续遍历数组元素
- 直到整个数组遍历完成
三、代码实现
方法二:未考虑奇数间、偶数间相对位置不变
public class Solution {
/**
* 调整数组顺序是奇数位于偶数前面
*/
public void reOrderArray(int [] array) {
//若数组不存在或为空
if(array==null || array.length==0){
return;
}
int start = 0; //头指针
int end = array.length-1; //尾指针
while(start < end){
//向后移动头指针,直到它指向偶数
while(start<end && (array[start] & 0x1)!=0){
start++;
}
//向前移动尾指针,直到它指向奇数
while(start<end && (array[end] & 0x1)==0){
end--;
}
//交换头指针指向的偶数 与尾指针指向的奇数 的位置
if(start < end){
int temp = array[start];
array[start] = array[end];
array[end] = temp;
}
}
}
}
运行结果:
方法三、可扩展解法
public class Solution {
/**
* 调整数组顺序是奇数位于偶数前面
*/
public void reOrderArray(int [] array) {
//若数组不存在或为空
if(array==null || array.length==0){
return;
}
int start = 0; //头指针
int end = array.length-1; //尾指针
while(start < end){
//向后移动头指针,直到它指向偶数
while(start<end && !isEven(array[start])){
start++;
}
//向前移动尾指针,直到它指向奇数
while(start<end && isEven(array[end])){
end--;
}
//交换头指针指向的偶数 与尾指针指向的奇数 的位置
if(start < end){
int temp = array[start];
array[start] = array[end];
array[end] = temp;
}
}
}
/**
*判断是否为偶数
*/
public boolean isEven(int n){
return (n & 0x1)==0;
}
}
方法四:考虑奇数间、偶数间相对位置不变
public class Solution {
/**
*插入排序
*/
public void reOrderArray(int [] array) {
int count = 0;//记录已经摆好位置的奇数的个数
int len = array.length-1;
//遍历数组中的每一个元素
for (int i = 0; i <= len; i++) {
//判断当前遍历元素是否为奇数
if(array[i]%2==1){
int j = i; //记录当前遍历元素
//若找到一个奇数,则向前遍历,与前面的偶数依次交换位置,直到将此奇数插入到上一次找到的奇数的末尾
while(j>count){
int temp = array[j];
array[j] = array[j-1];
array[j-1] = temp;
j--;
}
count++;
}
}
}
}