剑指offer第十三题。

题目描述

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

解题思路

这个题目最简单的思路自然是新开一个数组来存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Solution {
public void reOrderArray(int [] array) {
int[] temp = new int[array.length];
int count = 0;
for(int i=0;i<array.length;i++){
if(array[i] % 2 == 1){
count++;
}
}
int e = 0;
for(int i=0;i<array.length;i++){
if(array[i] % 2 == 1){
temp[e++] = array[i];
}else{
temp[count++] = array[i];
}
}
for(int i=0;i<temp.length;i++){
array[i] = temp[i];
}
}
}

不过确实有点low,应该不是出题者本意。我们可以在原地进行处理,基本思想同插入排序。

首先说明一下,本题用快排的话会非常复杂,几乎是做不出来。因为他要保证偶数与偶数,奇数与奇数相对的顺序不变。

要想保证偶数与偶数,奇数与奇数相对顺序不变,那么就不能简单地交换,办法是整体移动。我首先找到第一个偶数,然后从这个偶数开始找第一个奇数。两者不能直接交换,因为交换的话,在前面的偶数被调到了后面,不符合题意。

从偶数位置开始,依次往后挪一格,然后将第一个奇数放到当前偶数的位置。依次循环,到最后i或者j越界了说明已经全部调整好了。

我的答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Solution {
public void reOrderArray(int [] array) {
//非法判断
if(array.length == 0 || array == null){
return;
}

int i = 0 , j;
while(i < array.length){
//找到第一个偶数停止
while(i < array.length && !isEven(array[i])){
i++;
}
//从偶数位置开始,找第一个奇数
j = i + 1;
while(j < array.length && isEven(array[j])){
j++;
}
//这个j越界说明找不到奇数了,则后面没有奇数就结束了
if(j < array.length){
//从偶数位置开始到奇数位置整体向后移动一格,然后把这个奇数放到偶数位置即可
int tmp = array[j];
for(int j2 = j-1;j2 >= i;j2--){
array[j2+1] = array[j2];
}
array[i++] = tmp;
}else{
break;
}
}
}

//判断是否为偶数
private boolean isEven(int n){
if(n%2 == 0)
return true;
return false;
}
}