不难,难的是要写出最完美的方法,这里用了三种,如果实在不行第一种总写得出的
第一种:时复O(n),空复O(n),开辟一个额外数组用于辅助,遍历两次碰到奇数就直接push_back进去,第二次碰到偶数就push_back进去。或者碰到奇数直接放进去,然后从后往前,碰到偶数就从后往前放。
第二种:O(n^2)和O(1),冒泡排序,从前往后找到奇数就在循环内部往前遍历,如果遍历到奇数就直接break,因为按理说前面的奇数已经被处理完了,前面奇数的前面是不会有偶数的。如果遍历到偶数,就慢慢swap过去,将当前位j和j+1也就是奇数那一位交换。
第三种:O(n^2)和O(1),插排。k记录排好的奇数个数。好像其实和法2一样的,只不过它是检测是否是奇数,我们是从j遍历到k+1,一路交换过去就行了。
class Solution {
public:
void reOrderArray(vector<int> &array) {
//1第一种方法两种实现,第一次循环找奇数,第二次循环找偶数,全部push_back也行,像这样做也行
/*vector<int> res(array.size());
int left = 0, right = array.size() - 1;
for(int i = 0; i < array.size(); ++i){
if(array[i] % 2 == 1){
res[left++] = array[i];
}
}
for(int i = array.size() - 1; i >= 0; --i){
if(array[i] % 2 == 0){
res[right--] = array[i];
}
if(right < left) break;
}
for(int i = 0; i < array.size(); ++i){
array[i] = res[i];
}*/
/*2这题想拿offer必须原地排序,来一个冒泡的
从前往后遍历,遍历到第一个奇数时,找到奇数就退出,因为此奇数前面一定没有偶数了
找到偶数就逐个往前交换
for(int i = 0; i < array.size(); ++i){
if(array[i] % 2 == 1){
for(int j = i - 1; j >= 0; --j){
if(array[j] % 2 == 1) break;
swap(array[j+1],array[j]);
}
}
}*/
/*插入法,插完之后记得所有数“后移一位”,插入法的相对位置不变,稳定性
当前位是偶数,就继续往后找到第一个奇数,将这个奇数插到找到偶数前*/
int m = array.size();
int k = 0;//记录已经摆好位置的奇数的个数
for(int i = 0; i < m; i++){
if(array[i] % 2 == 1){//如果是奇数
int j = i;
while(j > k){//j >= k+1,一个一个往前换,顺便后移数组
int tmp = array[j];
array[j] = array[j-1];
array[j-1] = tmp;
j--;
}
k++;
}
}
}
};
用bubblesort,记得用一个bool值判断这一轮是否有交换,如果没有就可以直接退出了
vector<int> reOrderArray(vector<int>& array) {
// write code here
//要保证奇数和奇数相对位置不变,偶数和偶数相对位置不变,那就不可以随便交换了
//还是得用冒泡排序,内部从左往右交换,只和自己相邻一个交换,这样就不会出现1,4,6,5这样的情况交换后是
//1,5,6,4的情况了,我们只会让4和6换,换不了就是6和5,到下一轮就是4和5,
//总的来说就是一轮把最右边的偶数放到结尾处
bool isSorted = true;
for(int i = array.size()-1; i > 0 && isSorted; ++i){
isSorted = false;
for(int j = 0; j < i-1; ++j){
if(array[j] % 2 == 1) continue;
else if(array[j+1]%2 == 1){
isSorted = true;
swap(array[j],array[j+1]);
}
}
}
return array;
}