题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
如果不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的所有数字往前挪动一位。挪完之后再数组的末尾有一个空位,这时把该偶数放入这个空位。由于每碰到一个偶数就需要移动O(n)个数字,因此总的时间复杂度是O(n^2).
鉴于对时间复杂度的优化上,高效的解法是,维护两个指针,第一个指针初始化时指向数组第一个数字,它只向后移动;第二个指针初始化时指向数组的最后一个数字,它只向前移动;在这两个指针相遇之前,第一个指针总是位于第二个指针的前面。如果第一个指针指向的数字是偶数,并且第二个指针指向的数字是奇数,我们就交换着两个数字。
public static void ReorderOddEven(int[] datas)
{
if (datas == null || datas.Length <= 0)
{
return;
}
int begin = 0;
int end = datas.Length - 1;
int temp = -1;
while (begin < end)
{
// 向后移动begin,直到它指向偶数
while (begin < end && (datas[begin] & 1) != 0)
{
begin++;
}
// 向前移动pEnd,直到它指向奇数
while (begin < end && (datas[end] & 1) == 0)
{
end--;
}
if (begin < end)
{
// 交换偶数和奇数
temp = datas[begin];
datas[begin] = datas[end];
datas[end] = temp;
}
}
}
(2)可扩展性实现
当面试官再提问:如果把题目改成把数组中的数按照大小分为两部分,所有负数都在非负数的前面,又或者改改,变成把数组中的数分为两部分,能被3整除的数都在不能被3整除的数的前面,怎么办?这时应该明白面试官要求我们的不仅仅是要提供解决一个问题的办法,而是解决一系列同类型问题的通用方法。
回到新提出来的两个问题上来,要解决这两个问题,只需修改函数中的两处判断标准,而大的逻辑框架不需要改动。因此,将逻辑框架抽象出来,而把判断标准用一个单独的函数来判断数字是不是符合标准。