一、問題描述
輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
二、解題思路
兩個指針,一個首、一個尾。然後一個向前、一個向後判斷奇、偶,然後交換(類似於快排的思想)
三、代碼實現
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