题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
思路:拿到这一题,我想到了另外和这题类似的一道题,唯一不同是那个题目不要求奇数和奇数,偶数和偶数之间的相对位置不变。
给出那道题的解法:两个指针,第一个指向首,先后移动;第二个指向尾,向前移动。在两指针相遇前,如果第一个指针指向了偶数,第二个指针指向了奇数,交换。
代码:
public class Solution {
public static void reOrderArray(int[] array) {
if (array == null || array.length <= 0)
return;
int begin = 0;
int end = array.length - 1;
while (begin < end) {
while (begin < end && (array[begin] & 1) != 0) {
begin++;
}
while (begin < end && (array[end] & 1) == 0) {
end--;
}
if(begin<end){
int temp=array[begin];
array[begin]=array[end];
array[end]=temp;
}
}
}
public static void main(String[] args) {
int[] array={1,2,3,4,5};
reOrderArray(array);
for(int element:array)
System.out.print(element+" ");
}
}
为了考虑可扩展性,改进方法:
public class ReorderOddEven {
// 不能保证奇数和奇数,偶数和偶数之间的相对位置不变。
// 如果把题目改成,所有的负数在非负数前面,或者能被3整除的都在不能被3整除的前面,怎么在原来函数的基础上扩展?
// 回调函数:一个函数A以参数的形式传递给另一个函数B,在B中执行A,称A为回调函数,或者一个方法对象a传递给另一个方法对象b
// 总之,传递的不是基本类型,而是函数的指针(引用),称回调函数
// java中没有指针,怎么传递函数的指针?
// 定义一个包含回调函数的接口,并将接口对象传递给调用函数,则在调用函数执行时,会执行回调函数
public static interface CallBack {
boolean execute(int n);
}
public static void reOrderArray(int[] array, CallBack callBack) {
if (array == null || array.length <= 0)
return;
int begin = 0;
int end = array.length - 1;
// System.out.println(callBack.execute(array[begin+1]));
while (begin < end) {
while (begin < end && !callBack.execute(array[begin])) {
begin++;
}
while (begin < end && callBack.execute(array[end])) {
end--;
}
if (begin < end) {
int temp = array[begin];
array[begin] = array[end];
array[end] = temp;
}
}
}
public static boolean isEvent(int n) {
return (n & 1) == 0;
}
public static void main(String[] args) {
int[] array = { 1, 2, 3, 4, 5 };
reOrderArray(array, new CallBack() {
public boolean execute(int n) {
return isEvent(n);
}
});
for (int element : array)
System.out.print(element + " ");
}
}
为了奇数和奇数,偶数和偶数之间的相对位置不变。
改进代码如下:
package com.su.biancheng;
/**
* @title ReorderOddEven2.java
* @author Shuai
* @date 2016-4-10下午8:27:47
*/
public class ReorderOddEven2 {
//保证奇数和奇数,偶数和偶数之间的相对位置不变
//从头扫描这个数组,每碰到一个偶数,就把这个数之后的所有数往前移一位,这样数组末尾有个空位,把偶数放到这个空位
//这样做会有问题,如12345-->13452-->13524-->13542,偶数顺序改变
//改:1:碰到一个偶数,而且之后存在奇数时移动;不存在奇数,不动,但这样又多了一层循环,时间为O(n)
//122345-->123452-->134522-->135224
//改进2:碰到一个奇数,如果其前面有偶数就移位,这样只需要判断前一个数是不是偶数即可,时间为O(1)
//122345-->132245-->135224
//两层循环,外层循环扫描数组,内层循环移位,时间复杂度O(n^2)
public static void reOrderArray(int[] array,CallBack callBack) {
if (array == null || array.length <= 0)
return;
int i,j;
for (i=0;i<array.length;i++) {
int temp=array[i];
if(!callBack.execute(array[i])){
for(j=i-1;j>=0&&callBack.execute(array[j]);j--){
array[j+1]=array[j];
}
array[j+1]=temp;
}
}
}
public static boolean isEvent(int n) {
return (n & 1) == 0;
}
public static interface CallBack{
boolean execute(int n);
}
public static void main(String[] args) {
int[] array={1,2,3,4,5};
reOrderArray(array,new CallBack(){
public boolean execute(int n) {
return isEvent(n);
}
});
for(int element:array)
System.out.print(element+" ");
}
}