剑指 Offer 21. 调整数组顺序使奇数位于偶数前面

一、题目描述

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

示例:

输入:nums = [1,2,3,4]
输出:[1,3,2,4] 
注:[3,1,2,4] 也是正确的答案之一。

提示:

  1. 0 <= nums.length <= 50000
  2. 0 <= nums[i] <= 10000

二、题目解析

这道题目最终可以得到一个这样的数组,左边的部分都是奇数,右边的部分都是偶数。

如上图所示,绿色部分都是奇数,黄色部分都是偶数,并且此时 left 指向了奇数的最后一个元素,right 指向了偶数的第一个元素。

为了得到这样一个结果,需要执行如下的操作:

  • 1、设置两个指针 left 和 right,left 指向当前区间的最左侧元素,right 指向当前区间的最右侧元素。
  • 2、left 向右移动,right 向左移动,并且要使得 left 左边的元素(包含 left 本身)都是奇数,right 右边的元素(包含 right 本身)都是偶数。
  • 3、如果 left 指针指向的元素值是奇数,那么说明该元素在左侧了,观察其它的元素,即让 left 向右移动。
  • 4、如果 right 指针指向的元素值是偶数,那么说明该元素在右侧了,观察其它的元素,即让 right 向左移动。
  • 5、否则就说明,此时要么 left 指向的元素值为偶数,要么 right 指向的元素值为奇数,它们不在正确的位置上,需要交换一下。

为了帮助你更好的理解整个过程,我特意做了一组动画,点开可以查看

三、参考代码

// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
class Solution {
    public int[] exchange(int[] nums) {

        // 定义头指针 left 
        int left = 0 ;

        // 定义尾指针 right 
        int right = nums.length - 1;

        // 定义临时变量 tmp 
        int tmp;

        // 移动 left 和 right ,直到 left 在 right 右侧或者相遇为止
        while(left < right) {

            // 如果 left 指针指向的元素值是奇数,那么说明该元素在左侧了,观察其它的元素,即让 left 向右移动
            while(left < right && (nums[left] & 1) == 1) left++;

            // 如果 right 指针指向的元素值是偶数,那么说明该元素在右侧了,观察其它的元素,即让 right 向左移动
            while(left < right && (nums[right] & 1) == 0) right--;

            // 否则就说明,此时要么 left 指向的元素值为偶数,要么 right 指向的元素值为奇数
            // 交换这两个位置的元素
            tmp = nums[left];
            nums[left] = nums[right];
            nums[right] = tmp;
        }

        // 最后返回结果就行
        return nums;
    }
}