题目描述
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
难度简单96
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
提示:
0 <= nums.length <= 50000
1 <= nums[i] <= 10000
测试用例
- 功能测试(输入数组中的奇数、偶数交替出现;输入的数组中所有偶数都出现在奇数的前面;输入的数组所有奇数都出现在偶数的前面)
- 特殊输入测试(输入空指针;输入的数组只包含一个数字)
题目考点
- 考察应聘者的快速思维能力。
- 对于已经工作几年的应聘者,面试官还将考察其对扩展性的理解,要求应聘者写出的代码具有可重用性。
解题思路
只完成基本功能的解法
维护连个指针:第一个指针初始化时指向数组的第一个数字,它只向后移动;第二个指针指向数组的最后一个数字,它只向前移动。在两个指针相遇之前,第一个指针总是位于第二个指针前面。如果第一个指针指向的数字是偶数,并且第二个指针指向的数字是奇数,则交换这两个数字。
PS:为了避免重复交换,我们可以在可能交换之前,让两个指针分别向自己的方向扫描,直到第一个指针指向偶数,第二个指针指向奇数。
考虑可扩展的解法
这到题目是要求我们按照奇偶分类,如果我们要按照正负分类,我们第一反应应该是去该代码,但是这样很不好。耦合度太高,所以我们需要考虑扩展性。这里我们是可以使用 策略模式。
参考解题
只完成基本功能的解法
/**
* 调整数组顺序使奇数位于偶数前面
*/
public class Solution1 {
/**
* 只完成基本功能的解法
* @param array
*/
public void reOrderArray(int [] array) {
// 防止特殊输入
if (array == null || array.length == 0) {
return;
}
int i = 0;
int j = array.length-1;
while (i < j) {
// 第一个指针,直到遇见偶数,然后开始准备交换
while (i < j && (array[i] & 1) != 0) {
i++;
}
// 第二个指针,直到遇见奇数,然后开始准备交换
while (i < j && (array[j] & 1) == 0) {
j--;
}
// 开始交换
if (i < j) {
swapArray(array, i, j);
}
}
}
/**
* 交换数组的两个值
* @param array
* @param i
* @param j
*/
public void swapArray(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
考虑可扩展的解法
/**
* 重排序策略
*/
public interface ReorderStrategy {
/**
* 判断符合某种条件
* @param array
* @param index
*/
boolean reorderBySomething(int[] array, int index);
}
/**
* 按照奇偶重排序
*/
public class OddEventReorderStategy implements ReorderStrategy {
/**
* 返回是否为偶数
* @param array
* @param index
* @return
*/
@Override
public boolean reorderBySomething(int[] array, int index) {
return (array[index] & 1) == 0;
}
}
public class Solution2 {
/**
* 判断的策略
*/
private ReorderStrategy reorderStrategy;
public Solution2() {
}
public Solution2(ReorderStrategy reorderStrategy) {
this.reorderStrategy = reorderStrategy;
}
/**
* 只完成基本功能的解法
* @param array
*/
public void reOrderArray(int [] array) {
// 防止特殊输入
if (array == null || array.length == 0) {
return;
}
int i = 0;
int j = array.length-1;
while (i < j) {
// 第一个指针,直到遇见偶数,然后开始准备交换
while (i < j && !reorderStrategy.reorderBySomething(array, i)) {
i++;
}
// 第二个指针,直到遇见奇数,然后开始准备交换
while (i < j && reorderStrategy.reorderBySomething(array, j)) {
j--;
}
// 开始交换
if (i < j) {
swapArray(array, i, j);
}
}
}
/**
* 交换数组的两个值
* @param array
* @param i
* @param j
*/
public void swapArray(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
public static void main(String[] args) {
int[] array = new int[] {
2,4,4,6,8,10,1,3,5};
ReorderStrategy reorderStrategy = new OddEventReorderStategy();
Solution2 solution = new Solution2(reorderStrategy);
solution.reOrderArray(array);
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}