题目来源:牛客网-剑指Offer专题
题目地址:调整数组顺序使奇数位于偶数前面
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
题目解析
对于这道题,有三种实现方式,时间复杂度分别为 、 和 ,下面我们来逐一介绍:
方法一:
思路类似于插入排序:遍历
,当遇到array[i]
偶数时,就p=i+1
位置开始寻找第一个奇数。如果找到了,则将array[p]
移动到array[i]
前面。否则,说明数组的调整已经完成,遍历停止。
上图是某次遇到偶数时的执行图示,供大家理解。这个算法的时间复杂度为
。
public class Solution {
public void reOrderArray(int [] array) {
int size = array.length;
for (int i = 0; i < size; i++) {
if (array[i] % 2 == 0) {
int p = i + 1;
//寻找array[i]以后的第一个奇数
while (p < size && array[p] % 2 != 1) p++;
if (p < size) {
//array[p]移动到array[i]的位置,且将保持相对位置不变
int t = array[p];
for (int j = p; j > i; j--) {
array[j] = array[j - 1];
}
array[i] = t;
} else {
//说明已经完成了数组的调整
break;
}
}
}
}
}
方法二:
这个种做法的思路源于归并排序,是我参考Cyril-廖思睿博客的思路(长见识了)。
如果你学了归并排序,理解下面代码不会有任何难度,详情可以看注解(不懂留言也可 )。算法时间复杂度为
。
public class Solution {
public void reOrderArray(int [] array) {
if (array == null || array.length < 2) {
return ;
}
orderProcess(array, 0, array.length - 1);
}
public void orderProcess(int [] array, int left, int right) {
if (left == right) {
return ;
}
int mid = left + ((right - left) >> 1);
//进行划分操作
orderProcess(array, left, mid);
orderProcess(array, mid + 1, right);
//进行合并操作
mergeOrder(array, left, mid, right);
}
//进行合并操作
public void mergeOrder(int [] array, int left, int mid, int right) {
int len = right - left + 1, pLeft = left, pRight = mid + 1, p = 0;
//暂时存空间
int temp[] = new int[len];
//为了保持相对顺序不变,先放左边的奇数
while (pLeft <= mid && array[pLeft]%2 == 1) {
temp[p++] = array[pLeft++];
}
while (pRight <= right && array[pRight]%2 == 1) {
temp[p++] = array[pRight++];
}
//为了保持相对顺序不变,先放左边的偶数
while (pLeft <= mid) {
temp[p++] = array[pLeft++];
}
while (pRight <= right) {
temp[p++] = array[pRight++];
}
//将暂存空间中的数移回原数组中
for (int k = 0; k < len; k++) {
//注意相对位置
array[left + k] = temp[k];
}
}
}
方法三
这种方法是一种空间换时间的一种策略,多开一个专门用于存储的偶数的数组
,在遍历的过程中,将偶数按原来的相对顺序放到
中;而奇数也在原数组中按原来的相对顺序,进行紧凑操作(直接放到上一个奇数后面)。如下图所示:
最后,将偶数(
)接到回奇数(原数组)后面,就完成了我们的调整,时间复杂度为
。
public class Solution {
public void reOrderArray(int [] array) {
int size = array.length, s1 = 0, s2 = 0;
//专门用于存储的偶数的数组
int [] evens = new int[size];
for (int i = 0; i < size; i++) {
//筛选过程,将奇数和偶数分开
if (array[i] % 2 == 1) {
array[s1++] = array[i];
} else {
evens[s2++] = array[i];
}
}
//将偶数接到奇数后面
for (int i = 0; i < s2; i++) {
array[s1++] = even[i];
}
}
}
如果本文对你有所帮助,要记得点赞哦~