面試題21:輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
方法一:數組的引用作爲實參O(N)
class Solution {
public:
void reOrderArray(vector<int> &array) { //需要對數組進行修改,故數組引用組爲形參
vector<int> result;
int length = array.size();
for (int i = 0; i <length; ++i){
if (array[i] & 0x1 == 1)
result.push_back(array[i]);
}
for (int i = 0; i <length; ++i){
if((array[i] & 0x1) == 0) //(array[i] & 0x1)此處不加括號則報錯
result.push_back(array[i]);
}
array = result;
}
};
方法二:使用指針作爲形參
class Solution {
public:
void reOrderArray(int *pData, unsigned int length)
{
if(pData == nullptr || length == 0)
return;
int *pBegin = pData;
int *pEnd = pData + length - 1;
while(pBegin < pEnd)
{
// 向後移動pBegin,直到它指向偶數
while(pBegin < pEnd && (*pBegin & 0x1) != 0)
pBegin ++;
// 向前移動pEnd,直到它指向奇數
while(pBegin < pEnd && (*pEnd & 0x1) == 0)
pEnd --;
if(pBegin < pEnd)
{
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;
}
}
}
};
方法三:函數指針實現通用性
我們可以把這個邏輯框架抽象出來, 而把判斷的標準變成 個函數指針, 也就是用一個單獨的函數來判斷數字是不是符合標準。 這樣我們就把整個函數解糊成兩部分:一是判斷數字應該在數組前半部分還是後半部分的標準; 二是拆分數組的操作。
在下面的代碼中,函數Reor由r根據func的標準把數組pData分成兩部 分: 而函數isEven則是一個具體的標準, 即判斷一個數是不是偶數。 有了這兩個函數, 我們就可以很方便地把數組中的所有奇數移到偶數的前面。解耦的好處就是提高了代碼的重用性,爲功能擴展提供了便利。
class Solution{
public:
void ReorderOddEven_2(int *pData, unsigned int length)
{
Reorder(pData, length, isEven); //isEven函數名稱代表地址
}
void Reorder(int *pData, unsigned int length, bool (*func)(int))
{
if(pData == nullptr || length == 0)
return;
int *pBegin = pData;
int *pEnd = pData + length - 1;
while(pBegin < pEnd)
{
// 向後移動pBegin
while(pBegin < pEnd && !func(*pBegin))
pBegin ++;
// 向前移動pEnd
while(pBegin < pEnd && func(*pEnd))
pEnd --;
if(pBegin < pEnd)
{
int temp = *pBegin;
*pBegin = *pEnd;
*pEnd = temp;
}
}
}
bool isEven(int n)
{
return (n & 1) == 0;
}
};