数组 - 21.调整数组的顺序使奇数位于偶数之前

在这里插入图片描述
思路1:直接遍历数组遇到偶数就移动到下一个奇数后(类似插入排序)但是这种算法的时间复杂度会很高,每碰到一个偶数就要移动O(n)个单位。算法复杂度O(n^2);非常低效率
优化思路1,提供一个相同长度的大小的数组,原数组遍历,遇到偶数放到新数组的最后一个位置,奇数顺序放入新数组。这样算法复杂度会降低到O(n),但需要空间复杂度O(n)的支持
再度优化,直接定义两个指针,一个从前向后找偶数,一个从后向前找奇数,当两个指针都找到对应的数字时,那就交换位置,直到两个指针相遇为止。

    public void reOrderArray(int [] array) {
        if(array.length <= 1 || array == null) return ;
        
        int pBegin = 0 ;
        int pEnd = array.length-1;

        while(pBegin < pEnd){
            //偶数二进制最后一位一定为0
            while(pBegin < pEnd && (array[pBegin] & 1) != 0){
                pBegin++;
            }
            while(pBegin < pEnd && (array[pEnd] & 1)== 0){
                pEnd--;
            }
            if(pBegin < pEnd){
                int temp = array[pBegin];
                array[pBegin] = array[pEnd];
                array[pEnd] = temp;
            }
        }

    }

扩展:如果现在需求变成负数在前非负数再后怎么办?或者改成被三整除的数在前,不被整除的再后怎么处理。此时我们就要对方法进行解耦,我们把判断的依据当成参数去传进去。

public void reOrderArray1(int [] array, Compares c){
        //把它解耦成分组和分组选择,我们把分组的选择定义成接口,
        //如果是偶数在前奇数再后,那么就实现分组选择的接口中的方法,
        if(array.length <= 1 || array == null) return ;
        int pBegin = 0 ;
        int pEnd = array.length-1;

        while(pBegin < pEnd){
            //偶数二进制最后一位一定为0
            while(pBegin < pEnd && c.judge(array[pBegin])){
                pBegin++;
            }
            while(pBegin < pEnd && !c.judge(array[pBegin])){
                pEnd--;
            }
            if(pBegin < pEnd){
                int temp = array[pBegin];
                array[pBegin] = array[pEnd];
                array[pEnd] = temp;
            }
        }
    }
    interface Compares{
        boolean judge(int number);
    }
    class isEven implements Compares{
	//具体实现
        @Override
        public boolean judge(int number) {
            return (number & 1) == 0;
        }
    }

但是这样始终有一个缺陷,它无法实现稳定性。

思路2:
所以如果最终我们要让这种算法稳定,还是要使用双指针从前向后遍历,一个找奇数一个找偶数,找到则交换。但是同样我们也可以运用到解耦这个思想

 public void reOrderArray(int [] array){
        if(array.length < 2 || array == null) return;
        //插入排序的思想来解决稳定性
        int findEven = 0;
        int findOdd = 0;
        while(findEven < array.length) {
            while (findEven < array.length && (array[findEven] & 1) != 0) {
                findEven++;
            }
            findOdd = findEven + 1;
            while (findOdd < array.length && (array[findOdd] & 1) == 0) {
                findOdd++;
            }
            //找到第一个奇数之后,从偶数开始到奇数-1的位置向后移动,
            // 然后把奇数放到之前偶数的位置上
            if(findOdd < array.length){
                int temp = array[findOdd];
                 for (int i = findOdd - 1; i >= findEven; i--) {
                        array[i+1] = array[i];
                 }
                array[findEven++] = temp;
            }else{
                break;
            }
        }

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值