题目描述:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
解题思路:
我们可以借鉴快速排序的思想,通过设置两个指针来进行交换操作,从而减少移动次数,提高效率:
1. 第一个指针初始化时指向数组的第一个数字,它只向后移动;
2. 第二个指针初始化时指向数组的最后一个数字,它只向前移动;
第一个指针指向的数字是偶数,并且第二个指针指向的数字是奇数,我们就交换这两个数字。
Demo:
class Solution {
public:
// 使用函数指针提高扩展性
void reOrderArray(vector<int> &array, bool (*func)(int))
{
int begin = 0;
int end = array.size() - 1;
while (begin < end)
{
// 向后移动begin,直到它指向偶数
while (begin < end && !func(array[begin]))
{
begin++;
}
// 向前移动pEnd,直到它指向奇数
while (begin < end && func(array[end]))
{
end--;
}
if (begin < end)
swap(array[begin], array[end]);
}
}
bool test(int n)
{
return (n & 1) == 1; // 判断奇数
}
};
题目扩展:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解题思路:
1. 要想保证原有次序,则只能顺序移动或相邻交换;
2. p1指向新数组的第一个偶数的位置;
3. p2是从p1开始的往后第一个奇数的位置;
4. 将[p1,…,p2-1]的元素整体后移一位,将p2位置的元素插入到p1的位置;
Demo:
class Solution {
public:
void reOrderArray(vector<int> &array, bool (*func)(int))
{
// p1和p2指向两个奇数之间的一个区间,左开右闭
int p1 = 0, p2;
for (int i = 0; i < array.size(); ++i)
{
if (func(array[i]))
{
p2 = i;
}
else
continue;
// 将后面的奇数移动到前面一个奇数的后面,中间的偶数都要向后移动一位
int tmp = array[p2];
for (int j = p2; j > p1; --j)
{
array[j] = array[j - 1];
}
array[p1] = tmp;
// p1指向新数组的第一个偶数的位置
p1++;
}
}
bool test(int n)
{
return (n & 1) == 1; // 判断奇数
}
};
class Solution {
public:
void reOrderArray(vector<int> &array, bool (*func)(int))
{
// 使用额外空间分别存储奇数和偶数
vector<int> vec1;
vector<int> vec2;
for (auto a : array)
{
if (func(a))
vec1.push_back(a);
else
vec2.push_back(a);
}
int j = 0;
for (int i = 0; i < vec1.size(); ++i)
array[j++] = vec1[i];
for (int i = 0; i < vec2.size(); ++i)
array[j++] = vec2[i];
}
bool test(int n)
{
return (n & 1) == 1; // 判断奇数
}
};