剑指offer面试题21(java版):调整数组顺序使奇数位于偶数前面

welcome to my blog

剑指offer面试题21(java版):调整数组顺序使奇数位于偶数前面

题目描述

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

第三次做; 模拟快排的partition过程, 时间复杂度O(N),空间复杂度O(1)

//模拟一遍partition的过程, pivot是奇数; 时间复杂度O(N), 空间复杂度O(1)
class Solution {
    public int[] exchange(int[] nums) {
        //input check 
        if(nums==null || nums.length<2)
            return nums;
        int n=nums.length, small = -1, big=n, p=0;
        while(p<big){
            if(nums[p]%2==1)
                swap(nums, ++small, p++);
            else
                swap(nums, --big, p);
        }
        return nums;
    }
    private void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

笔记

  • 数组问题, 输入的数组长度可以为0, 这并不是异常
  • java中函数能作为参数吗? (试试内部类)

第二次做 利用了归并排序的思想 注意while下如何保证稳定性; 使用归并排序时我有个疑惑,就是如果arr[p1]和arr[p2]都是偶数怎么办? 我当时担心这两个偶数后面还有奇数, 其实如果arr[p1]和arr[p2]都是偶数, 说明p1,p2后面的元素也都是偶数!, 看来递归的过程理解的还不到位

  • 不是最优解, 时间复杂度O(NlogN) 空间复杂度O(N)
/*
保证相对位置不变, 得用类似稳定排序的思想
归并,冒泡,插入
*/
public class Solution {
    public void reOrderArray(int [] array) {
        if(array==null || array.length<2) return;
        mergeSort(array, 0, array.length-1);
    }
    public void mergeSort(int[] arr, int left, int right){
        //base case
        if(left==right) return;
        //
        int mid = left + ((right-left)>>1);
        mergeSort(arr, left, mid);
        mergeSort(arr, mid+1, right);
        merge(arr, left, mid, right);
    }
    public void merge(int[] arr, int left, int mid, int right){
        int[] help = new int[right - left + 1];
        int p1=left, p2=mid+1, i=0;
        while(p1<=mid && p2<=right){
            //注意如何保持相对位置不变
            //必须先判断p1,再判断p2
            if((arr[p1]&1)==1)
                help[i++] = arr[p1++];
            else if((arr[p2]&1)==1)
                help[i++] = arr[p2++];
            else
                help[i++] = arr[p1++];
        }
        while(p1<=mid)
            help[i++] = arr[p1++];
        while(p2<=right)
            help[i++] = arr[p2++];
        for(int k=0; k<help.length; k++)
            arr[left++] = help[k];
    }
}

第二次做 最优解(并非最优解, 最优解应该是使用partition的方法) 时间复杂度和空间复杂度都是O(N)

public class Solution {
    public void reOrderArray(int [] array) {
        if(array==null||array.length<2)return;
        int[] even = new int[array.length];
        int oddIndex=0, evenIndex=0;
        for(int i=0; i<array.length; i++){
            if((array[i]&1)==0)
                even[evenIndex++] = array[i];
            else
                array[oddIndex++] = array[i];
        }
        evenIndex=0;
        for(int i=oddIndex; i<array.length; i++)
            array[i] = even[evenIndex++];
    }
}

下面这段代码没有保证奇数和奇数, 偶数和偶数之间的相位置对会改变,如2,2,1

public class Solution {
    public void reOrderArray(int [] array) {
        // input check
        if(array.length < 1)
            throw new RuntimeException("invalid input");
        // execute
        int pStart = 0;
        int pEnd = array.length - 1;
        while(pStart < pEnd){
            while(pStart < pEnd && array[pStart]%2==1) // 当array[pStart]能够待在数组靠前的部分时,向后移动pStart,直到array[pStart]不能待在数组的靠前部分
                pStart++;
            while(pStart < pEnd && array[pEnd]%2==0) // 当array[pEnd]能够待在数组靠后的部分时,向前移动pEnd,直到array[pEnd]不能待在数组的靠后部分
                pEnd--;
            if(pStart < pEnd){
                int temp = array[pStart];
                array[pStart] = array[pEnd];
                array[pEnd] = temp;
            }
        }
    }
}

保证奇数和奇数, 偶数和偶数之间相对顺序的代码

public class Solution {
    public void reOrderArray(int [] array) {
        // input check 其实不用健壮性检查, 数组问题,可以输入长度为0的数组!
        //if(array.length < 1)
         //   return null;
         
        // execute
        int oddCnt =0;
        int evenCnt = 0;
        int[] arrayEven = new int[array.length];
        for(int i=0; i<array.length; i++){
            if(array[i]%2==1)
                array[oddCnt++] = array[i]; 
            else
                arrayEven[evenCnt++] = array[i];
        }
        evenCnt = 0;
        for(int i=oddCnt; i<array.length; i++) // oddCnt是第一个偶数的索引
            array[i] = arrayEven[evenCnt++];
    }
}

一个.java中只能有一个public class

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wBsRCRLC-1582115390880)(WEBRESOURCE71d4e50de6235f90254813e3137fafcc)]

你可能感兴趣的:(剑指offer,剑指offer,java)