剑指offer13__调整数组顺序使奇数位于偶数前面_题解
调整数组顺序使奇数位于偶数前面
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
分析
方案一:辅助数组
/**
时间复杂度:O(n)
空间复杂度:O(n)
**/
class Solution {
public:
void reOrderArray(vector<int> &array) {
vector<int> odd, even;
for(int x : array){
if(x & 1){
odd.push_back(x);//odd奇数
}else{
even.push_back(x);//even偶数
}
}
int i = 0;
//array.size() = odd.size() + even.size()
//将odd[0,odd.size()-1]中的奇数复制到array[0,odd.size()-1]
for(i = 0; i < odd.size(); i++){
array[i] = odd[i];
}
//将even[0,even.size()-1]中的偶数复制到array[odd.size(),array.size()-1]
for(int j = 0; j < even.size(); j++){
array[i + j] = even[j];//注意array的下标从odd.size()开始,故需要加上i
}
}
};
方案二:in-place就地算法
设置变量 \(i\) 表示奇数放好的下一个位置,初始 \(i=0\) 表示还没有一个奇数放好
设置变量 \(j\) 表示数组的下标,初始 \(j=0\) 表示从下标0开始遍历
①如果遇到偶数,\(j++\)
②如果遇到奇数,先将 \([i, j - 1]\)的数据整体向右移动 \(1\)位,将奇数插入到 \(i\) 号位置,然后 \(i\) 往后移动一个位置
③整个数组遍历完毕,结束
/**
时间复杂度:O(n^2)
空间复杂度:O(1)
**/
class Solution {
public:
// in-place算法
void reOrderArray(vector<int> &array)
{
int i = 0;//i表示奇数放好的下一个位置
for (int j = 0; j < array.size(); j++)
{
//如果遇到奇数
if (array[j] & 1)
{
int tmp = array[j];
//将[i,j-1]的数据整体向右移动1位
for (int k = j - 1; k >= i; k--)
{
array[k + 1] = array[k];
}
//将奇数插入到array[i],i向后移动1个位置
array[i++] = tmp;
}
}
}
};
方案三:STL库函数 \(stable\_partition()\)
\(stable\_partition()\) 函数定义在<algorithm>
头文件中,其语法格式如下:
BidirectionalIterator stable_partition
(BidirectionalIterator first,
BidirectionalIterator last,
UnaryPredicate pred);
其中,first 和 last 都为双向迭代器,其组合 [first, last) 用于指定该函数的作用范围;pred 用于指定筛选规则。同时,stable_partition() 函数还会返回一个双向迭代器,其指向的是两部分数据的分界位置,更确切地说,指向的是第二组数据中的第 1 个元素。
/**
时间复杂度:O(n)
空间复杂度:O(n)
**/
class Solution {
public:
void reOrderArray(vector<int> &array) {
stable_partition(array.begin(), array.end(), [](int x) {return x&1;} );
}
};