算法小知识-----04.29-----按奇偶排序数组

247 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情

周五了,五一假期来了

按奇偶排序数组

该题出自力扣的905题 - 按奇偶排序数组【简单题】

审题

给你一个整数数组 nums,将 nums 中的的所有偶数元素移动到数组的前面,后跟所有奇数元素。
返回满足此条件的 任一数组 作为答案。

  • 题型很简单,就是给出一个整型数组,需要把数组划分为两组,前半部分是偶数,后半部分是奇数,并且没有排序的要求

  • 首当其冲的便是想到双指针的对撞指针做法,在不断后移的过程中对调

  • 解法:对撞指针

    • 首先判断数组的长度是否等于1,如果等于1则直接返回,无论奇偶无意义了
    • 定义左指针和右指针,循环对撞指针
    • 首先判断两个指针当前的数值是否奇偶数,并且相对移动两个指针,直到当前互为奇偶数,则原地对调位置
    • 最后输出数组即可
  • 时间复杂度为O(n),虽然在for循环内有两个while循环,但是并不影响每个元素只被循环一次

  • 空间复杂度为O(1),因为是在原地处理数据的
    除此以外还有一种优化方案,就是数组内对调的实现

  • 一开始使用的是new 一个初始值作为中转,去调换两个数值

  • 可以使用异或,也就是利用 一个数异或两次另一个数 等于自己本身,去实现调换参数

  • 如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。

    • nums[l] ^= nums[r];
      nums[r] ^= nums[l];
      nums[l++]^=nums[r--];
      

编码

class Solution {
    public int[] sortArrayByParity(int[] nums) {
        if (nums.length == 1)return nums;
        int l = 0,r = nums.length-1;
        while (l<r){
            if ((nums[l] &1) == 1 && (nums[r] &1) != 1){
                int temp = nums[l];
                nums[l] = nums[r];
                nums[r] = temp;
            }
            while ( l<r &&(nums[l] &1) == 0){
                l++;
            }
            while ( l<r && (nums[r] &1) == 1) {
                r--;
            }
        }
        return nums;
    }
}

image.png