题目
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
分析
- 首先:奇数在前,偶数在后,类似荷兰旗问题。在偶数后的奇数需要移动到数组前面来。
- 其次:本题要求奇数和偶数原来的顺序不变,就需要用到类似冒泡排序的思想移动奇数或者偶数,保证原来的顺序不变。
- 如何移动:
思路大致都是一样的思想,具体实现不同:
1. (奇先法)最后的奇数在前面,偶数在后面,所以遍历数组,找到奇数就依次放到前面的位置。(有代码)
2. (偶后法)类似上一种,找到偶数就后移到末尾。(代码与1一致,不写出)
3. (无奇法)找到第一个偶数,就与其偶数后的第一位奇数按顺序交换,直到偶数找不到后面的奇数。
代码实现
1:根据奇数在前的写法:
if(array == null || array.length == 0){
return;
}
int m = 0;//记录前一次最末尾奇数的位置
int len = array.length;
for (int i = 0; i < len; i++) {
if(array[i] % 2 == 1){//为奇数,往前找偶数
int temp = array[i];
int j = i;
while(j > m){
array[j] = array[j - 1];
j--;
}
m = j + 1;
array[j] = temp;
}
}
}
2:偶数找后面奇数的方法:
if(array == null || array.length == 0){
return;
}
int i = 0;//偶数指针
int j = 0;//奇数指针
int len = array.length;
while(i < len){
if(array[i] % 2 == 0){//找到偶数,判断其后面的奇数
j = i + 1;
while(j < len){
if(array[j] % 2 == 1){
int temp = array[j];
while(j > i){
array[j] = array[j - 1];
j--;
}
array[i] = temp;
break;
}
j++;
}
}
i++;
}
}
荷兰旗问题
需要把小于基准的放在前面,基准放在中间,大于基准的放在最后。
public static int[] partition(int[] arr, int L, int R, int p) {
int less = L;
int more = R;
while(L < more) {
if(arr[L] < p) {
swap1(arr, less++, L++);
} else if (arr[L] > p) {
swap1(arr, more--, L);
} else {
L++;
}
}
return new int[] { less + 1, more - 1 };
}
private static void swap1(int[] arr,int i, int j){
//^异或符号
//当有相等的时候不行 会变成 0
/*
上面的三个 还会执行就是 1 = 1^ 1;执行三次 过程是这样的
1 = 1 ^ 1 -->0
0 = 0 ^ 0 -->0
0 = 0 ^ 0 -->0
*/
if(i == j){
return;
}
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public static void main(String[] args) {
int[] arr = {3,4,4,5,6,4,5,3,6,7,5,3};
int pivot = 3;
int left = 0;
int right = arr.length - 1;
partition(arr,0,right,3);
System.out.println(Arrays.toString(arr));
}
OUTPUT:[3, 3, 3, 6, 4, 5, 5, 6, 7, 5, 4, 4]