一、问题描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
二、解题思路
两个指针,一个首、一个尾。然后一个向前、一个向后判断奇、偶,然后交换(类似于快排的思想)
三、代码实现
void reOrderArray(vector<int> &a)
{
if(a.empty()) return;
int left = 0;
int right = a.size()-1;
while(left < right) //从两边向中间扫描
{
//left向后找,直到指向偶数
while(left<right && a[left]%2 != 0) left++;//若为奇数时,向后移动
//right向前找,直到指向奇数
while(left<right && a[right]%2 == 0) right--;//若为偶数,向前移动
//交换
swap(a[left], a[right]);
}
}
但是上述的方法 无法保证调整后,奇数与奇数之间,偶数与偶数之间相对位置不变。此方法和STL的算法partition很像。
如果想保证相对位置问题,需要使用类似于STL的stable_partition算法。
四、STL中的partition和stable_partition算法
这两个方法都用来将指定容器的元素根据指定的predicate函数分成两个子序列,其中满足predicate()函数的,即返回值为true的作为第一个序列[v.begin(), bound), 而[bound, v.end())的作为第二个序列。
两个方法的区别在于, partition()对于两个子序列中的元素并不排序,而stable_partition()则对两个子序列的元素也进行排序。(注意:上面说的排序,不是大小的排序,而是针对于原来的序列的顺序)
1. 两个函数的原型如下:
BidirectionalIterator partition ( BidirectionalIterator first, BidirectionalIterator last, Predicate pred );
BidirectionalIterator stable_partition ( BidirectionalIterator first, BidirectionalIterator last, Predicate pred );
2. 参数的说明如下:
① first, last 第一个和第二个参数说明给定源容器的范围 [first, last)
② pred 第三个参数给定进行分组的规则函数。布尔型返回值 对于返回true的所有元素作为第一个子序列,对于返回false的所有元素作为第二个子序列
pred例子如下:
bool IsOdd(int i)
{
return (i%2 == 1);
}
调用时:
这样的话,奇数在前、偶数在后
bound = partition(v.begin(), v.end(), IsOdd);
//Return value 返回值是 指向第二个子序列的首元素迭代器
cout << "奇数 in the vector are:" <<endl;
for(it = v.begin(); it != bound; it++)
cout<<*it<<" ";
cout<< "偶数 in the vector are:" <<endl;
for(it = bound; it != v.end(); it++)
cout<<*it<<" ";
结果:
奇数 in the vector are: 9 1 7 3 5
偶数 in the vector are: 4 6 2 8 0