剑指offer每日一刷-2017年11月24日(补2017年11月23日)

来源:互联网 发布:js弹出窗口居中 编辑:程序博客网 时间:2024/05/21 18:59

题目:

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

题目描述:

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


方法一:

1.要保证原有顺序,只要顺次移动或相邻交换

2.i从左到右遍历,找到第一个偶数

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

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

5.终止条件:j向后遍历查找失败。

//运行时间为15mspublic void reOrderArray(int[] array){if(array==null||array.length==0){return ;}int i=0,j;while(i<array.length){//判断是奇数,是偶数时跳出while,找到第一个偶数while(i<array.length&&!isEven(array[i])){i++;}j = i+1;//判断索引为j时是奇数还是偶数,奇数时跳出,找到i后面第一个奇数while(j<array.length&&isEven(array[j])){j++;}//跳出while循环后,j的值为索引i后面的第一个奇数的索引if(j<array.length){int tmp = array[j];//循环遍历,将索引为[i,j-1]之间的值整体向后移动一位for(int k=j-1;k>=i;k--){array[k+1] = array[k];}//将索引为j的值移到第一个偶数索引为i的处,然后将索引i+1,继续进行while循环判断array[i++]=tmp;}else{//出现这种情况的唯一可能,就是i=array.length-1,即i指向数组末尾时,j=i+1越界break;}}}//判断是否是偶数private boolean isEven(int n){if(n%2 == 0)return true;return false;}


方法二:

采用类似冒泡排序的两层循环方法

内层循环是将所有的奇数都向前移动一位,相对的所有的偶数向后移动一位,

奇数与奇数之间的相对位置不变,偶数和偶数间的相对位置不变

外层循环是多次循环实现数组前半部分为奇数,后半部分为偶数。

public void reOrderArray(int[] array){if(array.length==0 || array == null){return ;}    //两层循环,嵌套的话时间复杂度为O(n^2)    for(int i=0;i<array.length;i++){for(int j=0;j<array.length-1-i;j++){/* * 找出遇到第一个偶数后的第一个奇数,-1防止j+1越界, * -i:假设最后的数字奇数,向前挪动后,就不需要对最后的那一位进行移动,所以-i提高效率 */if(array[j]%2==0&&array[j+1]%2 == 1){//奇数和偶数调换位置,通过加法运算进行换值array[j] = array[j]+array[j+1];array[j+1] = array[j] -array[j+1];array[j] = array[j] -array[j+1];}}}}

方法三:插入排序

从前向后,找到奇数后,将奇数前面的所有偶数向后移动,奇数挪动到所有后移的偶数前。

//运行时间16ms,但是相比上面的两种方法,占用的内存少很多public void reOrderArray(int[] array){for(int i=1;i<array.length;i++){int target = array[i];if(array[i]%2 == 1){int j=i; //从索引1向后开始,第一个奇数出现的位置while(j>=1&&array[j-1]%2==0){ //奇数前的偶数array[j] = array[j-1]; //将偶数后移j--;}array[j] = target; //将记录的奇数,放到所有向后移动的偶数前面}}}



原创粉丝点击