描述
此题解是针对初学者的全面讲述,用三种方法来解决。
知识点:数组
难度:一星
题解
方法一:使用辅助数组
函数的类型为void func_name(array&),想让我们不开辟额外数组来解决,使用in-place就地算法。但是如果空间要求不高的话,我们还是可以开挂的。也就是开辟个额外数组,接下来的做法就非常简单了,遍历一次数组,遇到奇数直接放入新开的数组中,再遍历一次数组,遇到偶数就继续放入新开的数组。最后再进行一次copy。
代码如下:
class Solution { public: void reOrderArray(vector<int> &array) { vector<int> arr; for (const int v : array) { if (v&1) arr.push_back(v); // 奇数 } for (const int v : array) { if (!(v&1)) arr.push_back(v); // 偶数 } copy(arr.begin(), arr.end(), array.begin()); } };
时间复杂度:O(n)
空间复杂度:O(n)
方法二:in-place算法
如果不开辟额外数组该怎么做呢?
初始化操作:记录一个变量i表示已经将奇数放好的下一个位置,显然最开始i=0,表示还没有一个奇数放好。
j 表示数组的下标,初始值为0, 表示从下标0开始遍历。
- 如果遇到偶数,j++
- 如果遇到奇数,假设位置为j,就将此奇数插入到i所指的位置,然后i往后移动一个位置,在插入之前,显然会涉及到数据的移动,也就是将[i,j-1]整体往后移动。
- 直到整个数组遍历完毕,结束
代码如下:class Solution { public: void reOrderArray(vector<int> &array) { int i = 0; for (int j=0; j<array.size(); ++j) { if (array[j]&1) { int tmp = array[j]; for (int k=j-1; k>=i; --k) { array[k+1] = array[k]; } array[i++] = tmp; } } } };
时间复杂度:O(n^2),假设数组中一般偶数在前,一半奇数在后,每次都要移动n/2个元素,是n^2/4
空间复杂度:O(1)
方法三:使用STL库函数stable_partition()
函数原型:template< class BidirIt, class UnaryPredicate > BidirIt stable_partition( BidirIt first, BidirIt last, UnaryPredicate p );
第三个参数P可传入一个仿函数,函数指针,Lambda表达式,这里所示代码为Lambda表达式。
函数的意思是:对传入的区间[first, last)中的每个值进行P(value)判断,如果为真,就放入左边,并且保持稳定。
class Solution { public: void reOrderArray(vector<int> &array) { stable_partition(array.begin(), array.end(), [](int x) {return x&1;} ); } };
时间复杂度:O(n)
空间复杂度:O(n),内部使用了额外数组