剑指offer之面试题14:调整数组顺序使奇数位于偶数前面

题目描述

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

思路:拿到这一题,我想到了另外和这题类似的一道题,唯一不同是那个题目不要求奇数和奇数,偶数和偶数之间的相对位置不变。给出那道题的解法:两个指针,第一个指向首,先后移动;第二个指向尾,向前移动。在两指针相遇前,如果第一个指针指向了偶数,第二个指针指向了奇数,交换。

代码:

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+" ");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值