剑指Offer_#21_调整数组顺序使奇数位于偶数前面

剑指Offer_#21_调整数组顺序使奇数位于偶数前面

Contents

题目

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

示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4] 
注:[3,1,2,4] 也是正确的答案之一。
提示:
1 <= nums.length <= 50000
1 <= nums[i] <= 10000

思路分析

1.暴力循环

最简单的思路是从前往后遍历数组,每次遇到一个偶数,就把这个偶数放到最后一位,把偶数后面的元素逐个向前移动一位。每次挪动数字的时间复杂度是O(n),整体的时间复杂度是O(n2),不推荐。

2.左右双指针

设置前后两个指针leftright,分别向后和向前遍历,left指针寻找位于数组前半部分的偶数,right指针寻找位于数组后半部分的奇数,然后将这两个数字交换。

3.左右双指针+临时数组

申请一个临时数组temp,左右指针leftright分别指向临时数组temp的左右两侧。然后从前到后遍历原数组nums,遇到奇数则放到templeft位置,遇到偶数则放到tempright位置。

4.快慢双指针

设置一个快指针fast和一个慢指针slowfast逐个遍历数组,寻找下一个奇数,slow遍历的是待交换的数组元素。每次fast搜索到奇数,就和slow交换。

解答

1.左右双指针

class Solution {
    public int[] exchange(int[] nums) {
        int left = 0,right = nums.length - 1;
        while(left < right){
            while(left < right && nums[left] % 2 != 0){//右移左指针直到遇到偶数
                left++;
            }
            while(left < right && nums[right] % 2 !=1){//左移右指针直到遇到奇数
                right--; 
            }
            if(left < right){//left和right分别指向偶数和奇数,将他们交换位置
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
            }
        }
        return nums;
    }
}

修改循环条件
left<right这个条件感觉很模糊,其实也属于没有显式定义出所有条件,而是一个隐含了left,right不越界的信息,可以把left,right不越界的条件显式写出。

class Solution {
    public int[] exchange(int[] nums) {
        int left = 0, right = nums.length - 1;
        while(left < right){
            //左指针不越界,并且指向奇数,就继续右移
            while(left <= nums.length - 1 && nums[left] % 2 == 1) left++;
            //右指针不越界,并且指向偶数,就继续左移
            while(right >= 0 && nums[right] % 2 == 0) right--;
            //指针不越界,并且left < right,就交换left和right指针指向的值
            if(left <= nums.length - 1 && right >= 0 && left < right){
                int tmp = nums[left];
                nums[left] =  nums[right];
                nums[right] = tmp;
            }
        }
        return nums;
    }
}
posted @ 2020-06-29 18:03  Howfar's  阅读(168)  评论(0)    收藏  举报