JZ81 调整数组顺序使奇数位于偶数前面

题目描述

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分

这个题目要求把奇数放在数组的前半部分,偶数放在数组的后半部分,因此所有的奇数应该位于偶数的前面,也就是说我们在扫描这个数组的时候,如果发现有偶数在奇数的前面,我们可以交换他们的数序,交换之后就符合要求了。

因此我们可以维护两个指针,第一个指针初始化时指向数组的第一个数字,它只向后移动;第二个指针初始化时指向数组的最后一个数字,它指向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针的前面。如果第一个指针的数字是偶数,并且第二个指针指向的数字是奇数,我们就交换两个数字,代码如下:

public int[] recorderOddEven(int[] nums, int length) {
    if(nums == null || length <=0)
        return null;
    int left = 0;
    int right = length - 1;
    
    //left指针要位于right指针前
    while(left < right){
        while(left < right && (nums[left] & 1) == 1){ //如果是奇数则继续遍历
            left++;
        }
        while(left < right && (nums[right] & 1) == 0 ){//如果是偶数继续遍历
            right--;
        }
        //交换奇数和偶数的位置
        if(left < right){
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
        }
    
    }
    return nums;

}

扩展:

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

思路:

1、要想保证原有的次序,则只能顺序移动或者相邻交换;

2、i 从左到右开始遍历,找到第一个偶数;

3、j 从 i+1 开始向后找,直到找到第一个奇数;

4、将 [ i , ... . j - 1 ] 的元素整体后移一位,最后将找到的奇数放入 i 位置,然后 i++;

5、终止条件,j 向后遍历查找失败,即后面没有奇数了。


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

    if(nums == null || nums.length <= 0){
        return null;
    }
    int i = 0;
    while(i < nums.length){
        while(i < nums.length && (nums[i] & 1) == 1){
            i++;
        }
        //i指向偶数时,j从i+1开始向后遍历找奇数
        int j = i + 1;
        while(j < nums.length && (nums[j] & 1) == 0){
            j++;
        }
        if(j < nums.length){
            //将[i,...,j-1]的元素整体后移1位,最后将找到的奇数放入i位置
            int temp = nums[j];
            for(int k = j-1;k >= i;k--){
                nums[k+1] = nums[k];
            }
            nums[i++] = temp;
        }
        else{
            break;
        }
    }
    return nums;
    
}

上面这种解法每次发现一个奇数在偶数后面,就需要搬移他们之间所有的元素,时间复杂度为O(n^{2^{^{}}}),下面我们将使用一种空间换时间的思想,将时间复杂度降低为O(n)。具体做法如下:

首先统计奇数的个数,然后新建一个与原数组等长的数组,设置两个指针,奇数指针从0开始,偶数指针从奇数个数的末尾开始遍历填数。

public int[] reOrderArray(int[] nums) {
    if(nums == null || nums.length <= 0)
        return null;

    int oddCount = 0,oddIndex = 0;
    //统计奇数的个数
    for(int i =0; i < nums.length;i++){

        if((nums[i] & 1) == 1){
            oddCount++;
        }
    }
   int[] newNums = new int[nums.length];
   for(int i = 0;i < nums.length;i++){
       if((nums[i] & 1) == 1) {
           newNums[oddIndex++] = nums[i];     
       }
       else{
           newNums[oddCount++] = nums[i];
       }
   }
   for(int i = 0; i < nums.length; i++){
        nums[i] = newNums[i];
    }
    return nums;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值